@pylonsync/create-pylon 0.19.1 → 0.20.0

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 (675) hide show
  1. package/bin/create-pylon.js +30 -7
  2. package/package.json +1 -1
  3. package/templates/agency/.env.example +7 -0
  4. package/templates/agency/README.md +28 -3
  5. package/templates/agency/app/(marketing)/contact-form.tsx +20 -18
  6. package/templates/agency/app/(marketing)/page.tsx +3 -3
  7. package/templates/agency/app/(marketing)/work/page.tsx +3 -3
  8. package/templates/agency/app/auth-form.tsx +4 -4
  9. package/templates/agency/app/dashboard/dashboard-client.tsx +110 -64
  10. package/templates/agency/app/dashboard/page.tsx +14 -16
  11. package/templates/agency/app/icon.svg +3 -0
  12. package/templates/agency/app/login/page.tsx +12 -14
  13. package/templates/agency/components/marketing.tsx +12 -5
  14. package/templates/agency/functions/seedStudioBackoffice.ts +42 -11
  15. package/templates/agency/lib/agency.ts +22 -0
  16. package/templates/agency/lib/demo.ts +118 -0
  17. package/templates/agency/lib/site.config.ts +19 -13
  18. package/templates/agency/public/favicon.ico +0 -0
  19. package/templates/agency/tests/agency.test.ts +57 -0
  20. package/templates/ai-chat/.env.example +13 -27
  21. package/templates/ai-chat/README.md +53 -60
  22. package/templates/ai-chat/app/(chat)/c/[id]/page.tsx +19 -0
  23. package/templates/ai-chat/app/(chat)/chat-client.tsx +657 -622
  24. package/templates/ai-chat/app/(chat)/layout.tsx +6 -43
  25. package/templates/ai-chat/app/(chat)/not-found.tsx +6 -10
  26. package/templates/ai-chat/app/(chat)/page.tsx +7 -11
  27. package/templates/ai-chat/app/auth-form.tsx +45 -38
  28. package/templates/ai-chat/app/error.tsx +9 -12
  29. package/templates/ai-chat/app/globals.css +464 -102
  30. package/templates/ai-chat/app/layout.tsx +11 -19
  31. package/templates/ai-chat/app/login/page.tsx +39 -24
  32. package/templates/ai-chat/app.ts +118 -43
  33. package/templates/ai-chat/components/chat/composer.tsx +193 -0
  34. package/templates/ai-chat/components/chat/empty-state.tsx +65 -0
  35. package/templates/ai-chat/components/chat/icons.tsx +198 -0
  36. package/templates/ai-chat/components/chat/markdown.tsx +164 -0
  37. package/templates/ai-chat/components/chat/message.tsx +183 -0
  38. package/templates/ai-chat/components/chat/setup.tsx +71 -0
  39. package/templates/ai-chat/components/chat/sidebar.tsx +288 -0
  40. package/templates/ai-chat/functions/_beginTurn.ts +145 -0
  41. package/templates/ai-chat/functions/_finishTurn.ts +55 -0
  42. package/templates/ai-chat/functions/assistantStatus.ts +13 -0
  43. package/templates/ai-chat/functions/claimGuestHistory.ts +39 -0
  44. package/templates/ai-chat/functions/createConversation.ts +28 -0
  45. package/templates/ai-chat/functions/deleteConversation.ts +15 -20
  46. package/templates/ai-chat/functions/prepareGuestClaim.ts +32 -0
  47. package/templates/ai-chat/functions/renameConversation.ts +19 -0
  48. package/templates/ai-chat/functions/respond.ts +88 -0
  49. package/templates/ai-chat/functions/seedExamples.ts +46 -0
  50. package/templates/ai-chat/functions/stopResponse.ts +30 -0
  51. package/templates/ai-chat/lib/brand-icon.ts +7 -0
  52. package/templates/ai-chat/lib/chat.ts +277 -0
  53. package/templates/ai-chat/lib/claim.ts +15 -0
  54. package/templates/ai-chat/lib/examples.ts +179 -0
  55. package/templates/ai-chat/lib/highlight.ts +107 -0
  56. package/templates/ai-chat/lib/markdown.ts +317 -0
  57. package/templates/ai-chat/lib/provider.ts +38 -0
  58. package/templates/ai-chat/lib/site.config.ts +55 -39
  59. package/templates/ai-chat/tests/chat.test.ts +174 -0
  60. package/templates/ai-chat/tests/components.test.tsx +57 -0
  61. package/templates/ai-chat/tests/markdown.test.ts +88 -0
  62. package/templates/ai-chat/tests/provider.test.ts +32 -0
  63. package/templates/backend/consumer/apps/api/app/layout.tsx +33 -0
  64. package/templates/backend/consumer/apps/api/app/page.tsx +54 -0
  65. package/templates/backend/consumer/apps/api/app.ts +166 -0
  66. package/templates/backend/consumer/apps/api/functions/addComment.ts +24 -0
  67. package/templates/backend/consumer/apps/api/functions/createPost.ts +19 -36
  68. package/templates/backend/consumer/apps/api/functions/deletePost.ts +15 -13
  69. package/templates/backend/consumer/apps/api/functions/myProfile.ts +5 -8
  70. package/templates/backend/consumer/apps/api/functions/seedDemo.ts +95 -0
  71. package/templates/backend/consumer/apps/api/functions/setFollow.ts +36 -0
  72. package/templates/backend/consumer/apps/api/functions/setLike.ts +36 -0
  73. package/templates/backend/consumer/apps/api/functions/upsertProfile.ts +43 -37
  74. package/templates/backend/consumer/apps/api/lib/seed.ts +89 -0
  75. package/templates/backend/consumer/apps/api/lib/social.ts +50 -0
  76. package/templates/backend/consumer/apps/api/package.json +8 -2
  77. package/templates/backend/consumer/apps/api/public/images/posts/arch.jpg +0 -0
  78. package/templates/backend/consumer/apps/api/public/images/posts/coffee.jpg +0 -0
  79. package/templates/backend/consumer/apps/api/public/images/posts/dog.jpg +0 -0
  80. package/templates/backend/consumer/apps/api/public/images/posts/lisbon.jpg +0 -0
  81. package/templates/backend/consumer/apps/api/public/images/posts/ramen.jpg +0 -0
  82. package/templates/backend/consumer/apps/api/public/images/posts/run.jpg +0 -0
  83. package/templates/backend/consumer/apps/api/public/images/posts/sunset.jpg +0 -0
  84. package/templates/backend/consumer/apps/api/tsconfig.json +12 -2
  85. package/templates/chat/README.md +43 -21
  86. package/templates/chat/app/chat-client.tsx +495 -85
  87. package/templates/chat/app/error.tsx +1 -1
  88. package/templates/chat/app/globals.css +170 -54
  89. package/templates/chat/app/layout.tsx +12 -9
  90. package/templates/chat/app/not-found.tsx +4 -2
  91. package/templates/chat/app/page.tsx +9 -19
  92. package/templates/chat/app.ts +96 -17
  93. package/templates/chat/components/chat/avatar.tsx +45 -0
  94. package/templates/chat/components/chat/composer.tsx +110 -0
  95. package/templates/chat/components/chat/message-list.tsx +285 -0
  96. package/templates/chat/components/chat/sidebar.tsx +190 -0
  97. package/templates/chat/functions/joinChat.ts +83 -0
  98. package/templates/chat/functions/renameMember.ts +25 -0
  99. package/templates/chat/lib/chat.ts +188 -0
  100. package/templates/chat/lib/seed.ts +78 -0
  101. package/templates/chat/tests/chat.test.ts +159 -0
  102. package/templates/chat/tests/composer.test.tsx +54 -0
  103. package/templates/consumer/README.md +3 -3
  104. package/templates/consumer/app/globals.css +10 -3
  105. package/templates/consumer/app/icon.svg +1 -0
  106. package/templates/consumer/components/social/avatar.tsx +25 -11
  107. package/templates/consumer/functions/seedFeed.ts +3 -3
  108. package/templates/consumer/lib/seed.ts +43 -85
  109. package/templates/consumer/public/favicon.ico +0 -0
  110. package/templates/consumer/public/images/posts/arch.jpg +0 -0
  111. package/templates/consumer/public/images/posts/coffee.jpg +0 -0
  112. package/templates/consumer/public/images/posts/dog.jpg +0 -0
  113. package/templates/consumer/public/images/posts/lisbon.jpg +0 -0
  114. package/templates/consumer/public/images/posts/ramen.jpg +0 -0
  115. package/templates/consumer/public/images/posts/run.jpg +0 -0
  116. package/templates/consumer/public/images/posts/sunset.jpg +0 -0
  117. package/templates/consumer/tests/seed.test.ts +39 -0
  118. package/templates/creator/.env.example +7 -0
  119. package/templates/creator/README.md +24 -5
  120. package/templates/creator/app/(marketing)/newsletter-signup.tsx +33 -12
  121. package/templates/creator/app/auth-form.tsx +7 -7
  122. package/templates/creator/app/dashboard/dashboard-client.tsx +137 -100
  123. package/templates/creator/app/dashboard/page.tsx +18 -18
  124. package/templates/creator/app/icon.svg +2 -0
  125. package/templates/creator/app/login/page.tsx +14 -14
  126. package/templates/creator/app.ts +4 -4
  127. package/templates/creator/functions/seedDemo.ts +32 -0
  128. package/templates/creator/functions/subscribe.ts +4 -15
  129. package/templates/creator/lib/demo.ts +94 -0
  130. package/templates/creator/lib/site.config.ts +15 -10
  131. package/templates/creator/lib/stats.ts +35 -0
  132. package/templates/creator/public/favicon.ico +0 -0
  133. package/templates/creator/tests/counter.test.ts +92 -0
  134. package/templates/creator/tests/live-count.test.tsx +45 -0
  135. package/templates/crm/README.md +22 -1
  136. package/templates/crm/app/apple-icon.png +0 -0
  137. package/templates/crm/app/companies/companies-view.tsx +32 -14
  138. package/templates/crm/app/companies/page.tsx +2 -1
  139. package/templates/crm/app/contacts/contacts-view.tsx +34 -10
  140. package/templates/crm/app/contacts/page.tsx +2 -1
  141. package/templates/crm/app/deals/[id]/deal-view.tsx +137 -98
  142. package/templates/crm/app/deals/[id]/page.tsx +2 -1
  143. package/templates/crm/app/globals.css +29 -14
  144. package/templates/crm/app/icon.svg +1 -0
  145. package/templates/crm/app/layout.tsx +7 -5
  146. package/templates/crm/app/page.tsx +2 -1
  147. package/templates/crm/app/pipeline-view.tsx +5 -5
  148. package/templates/crm/app/workspace.tsx +29 -17
  149. package/templates/crm/app.ts +5 -5
  150. package/templates/crm/components/activity-timeline.tsx +14 -4
  151. package/templates/crm/components/app-shell.tsx +94 -0
  152. package/templates/crm/components/auth-form.tsx +35 -5
  153. package/templates/crm/components/avatar.tsx +5 -1
  154. package/templates/crm/components/board-skeleton.tsx +5 -5
  155. package/templates/crm/components/brand-mark.tsx +25 -0
  156. package/templates/crm/components/command-palette.tsx +17 -17
  157. package/templates/crm/components/data-table.tsx +97 -36
  158. package/templates/crm/components/deal-card.tsx +23 -27
  159. package/templates/crm/components/filter-tabs.tsx +101 -0
  160. package/templates/crm/components/metrics-bar.tsx +6 -6
  161. package/templates/crm/components/nav.tsx +15 -0
  162. package/templates/crm/components/page-header.tsx +43 -7
  163. package/templates/crm/components/pipeline-board.tsx +16 -10
  164. package/templates/crm/components/require-auth.tsx +24 -26
  165. package/templates/crm/components/sidebar.tsx +54 -49
  166. package/templates/crm/components/stage-badge.tsx +4 -2
  167. package/templates/crm/components/ui/button.tsx +5 -4
  168. package/templates/crm/components/ui/dialog.tsx +1 -1
  169. package/templates/crm/components/ui/input.tsx +1 -1
  170. package/templates/crm/components/ui/select.tsx +1 -1
  171. package/templates/crm/components/ui/textarea.tsx +1 -1
  172. package/templates/crm/functions/seedWorkspace.ts +32 -17
  173. package/templates/crm/lib/brand.ts +9 -0
  174. package/templates/crm/lib/demo-team.ts +51 -0
  175. package/templates/crm/lib/pipeline.ts +37 -0
  176. package/templates/crm/lib/search.ts +4 -3
  177. package/templates/crm/lib/seed.ts +53 -8
  178. package/templates/crm/public/favicon.ico +0 -0
  179. package/templates/crm/tests/components.test.tsx +5 -5
  180. package/templates/crm/tests/demo-team.test.ts +18 -0
  181. package/templates/crm/tests/pipeline.test.ts +59 -3
  182. package/templates/directory/.env.example +7 -0
  183. package/templates/directory/README.md +22 -3
  184. package/templates/directory/app/(marketing)/directory-browse.tsx +30 -12
  185. package/templates/directory/app/(marketing)/page.tsx +6 -4
  186. package/templates/directory/app/auth-form.tsx +4 -4
  187. package/templates/directory/app/dashboard/dashboard-client.tsx +177 -90
  188. package/templates/directory/app/dashboard/page.tsx +16 -14
  189. package/templates/directory/app/icon.svg +4 -0
  190. package/templates/directory/app/login/page.tsx +16 -15
  191. package/templates/directory/functions/seedDemo.ts +43 -0
  192. package/templates/directory/lib/demo.ts +145 -0
  193. package/templates/directory/lib/directory.ts +27 -0
  194. package/templates/directory/lib/site.config.ts +21 -16
  195. package/templates/directory/public/favicon.ico +0 -0
  196. package/templates/directory/tests/directory.test.ts +46 -0
  197. package/templates/expo/consumer/apps/expo/App.tsx +360 -288
  198. package/templates/expo/consumer/apps/expo/app.json +9 -1
  199. package/templates/expo/consumer/apps/expo/package.json +2 -1
  200. package/templates/helpdesk/README.md +21 -0
  201. package/templates/helpdesk/app/apple-icon.png +0 -0
  202. package/templates/helpdesk/app/customers/customers-view.tsx +23 -7
  203. package/templates/helpdesk/app/customers/page.tsx +2 -1
  204. package/templates/helpdesk/app/globals.css +29 -14
  205. package/templates/helpdesk/app/icon.svg +1 -0
  206. package/templates/helpdesk/app/inbox-view.tsx +66 -47
  207. package/templates/helpdesk/app/layout.tsx +7 -5
  208. package/templates/helpdesk/app/page.tsx +4 -7
  209. package/templates/helpdesk/app/tickets/[id]/page.tsx +2 -1
  210. package/templates/helpdesk/app/tickets/[id]/ticket-view.tsx +134 -97
  211. package/templates/helpdesk/app/workspace.tsx +33 -22
  212. package/templates/helpdesk/app.ts +2 -2
  213. package/templates/helpdesk/components/app-shell.tsx +94 -0
  214. package/templates/helpdesk/components/auth-form.tsx +35 -5
  215. package/templates/helpdesk/components/avatar.tsx +5 -1
  216. package/templates/helpdesk/components/brand-mark.tsx +28 -0
  217. package/templates/helpdesk/components/command-palette.tsx +17 -17
  218. package/templates/helpdesk/components/data-table.tsx +97 -36
  219. package/templates/helpdesk/components/filter-tabs.tsx +101 -0
  220. package/templates/helpdesk/components/nav.tsx +14 -0
  221. package/templates/helpdesk/components/page-header.tsx +43 -7
  222. package/templates/helpdesk/components/priority-badge.tsx +49 -6
  223. package/templates/helpdesk/components/require-auth.tsx +24 -26
  224. package/templates/helpdesk/components/sidebar.tsx +54 -48
  225. package/templates/helpdesk/components/sla-indicator.tsx +5 -8
  226. package/templates/helpdesk/components/thread.tsx +7 -7
  227. package/templates/helpdesk/components/ticket-list.tsx +79 -19
  228. package/templates/helpdesk/components/ui/button.tsx +5 -4
  229. package/templates/helpdesk/components/ui/dialog.tsx +1 -1
  230. package/templates/helpdesk/components/ui/input.tsx +1 -1
  231. package/templates/helpdesk/components/ui/select.tsx +1 -1
  232. package/templates/helpdesk/components/ui/textarea.tsx +1 -1
  233. package/templates/helpdesk/functions/seedWorkspace.ts +25 -15
  234. package/templates/helpdesk/lib/brand.ts +9 -0
  235. package/templates/helpdesk/lib/demo-team.ts +51 -0
  236. package/templates/helpdesk/lib/search.ts +4 -3
  237. package/templates/helpdesk/lib/seed.ts +43 -2
  238. package/templates/helpdesk/lib/tickets.ts +68 -20
  239. package/templates/helpdesk/public/favicon.ico +0 -0
  240. package/templates/helpdesk/tests/components.test.tsx +10 -0
  241. package/templates/helpdesk/tests/demo-team.test.ts +18 -0
  242. package/templates/helpdesk/tests/tickets.test.ts +70 -0
  243. package/templates/imessage/.env.example +49 -0
  244. package/templates/imessage/AGENTS.md +153 -0
  245. package/templates/imessage/CLAUDE.md +7 -0
  246. package/templates/imessage/README.md +187 -0
  247. package/templates/imessage/app/console.tsx +382 -0
  248. package/templates/imessage/app/contacts/page.tsx +13 -0
  249. package/templates/imessage/app/error.tsx +16 -0
  250. package/templates/imessage/app/gate.tsx +31 -0
  251. package/templates/imessage/app/globals.css +183 -0
  252. package/templates/imessage/app/layout.tsx +17 -0
  253. package/templates/imessage/app/login/login-form.tsx +115 -0
  254. package/templates/imessage/app/login/page.tsx +30 -0
  255. package/templates/imessage/app/not-found.tsx +13 -0
  256. package/templates/imessage/app/page.tsx +14 -0
  257. package/templates/imessage/app/robots.ts +6 -0
  258. package/templates/imessage/app/setup/page.tsx +13 -0
  259. package/templates/imessage/app/sign-out.tsx +20 -0
  260. package/templates/imessage/app.ts +299 -0
  261. package/templates/imessage/bunfig +4 -0
  262. package/templates/imessage/components/avatar.tsx +46 -0
  263. package/templates/imessage/components/contact-panel.tsx +263 -0
  264. package/templates/imessage/components/contacts-view.tsx +172 -0
  265. package/templates/imessage/components/conversation-list.tsx +129 -0
  266. package/templates/imessage/components/nav-rail.tsx +67 -0
  267. package/templates/imessage/components/setup-view.tsx +408 -0
  268. package/templates/imessage/components/thread.tsx +229 -0
  269. package/templates/imessage/components/ui/badge.tsx +37 -0
  270. package/templates/imessage/components/ui/button.tsx +56 -0
  271. package/templates/imessage/components/ui/card.tsx +90 -0
  272. package/templates/imessage/components/ui/dialog.tsx +110 -0
  273. package/templates/imessage/components/ui/input.tsx +30 -0
  274. package/templates/imessage/components/ui/label.tsx +21 -0
  275. package/templates/imessage/components/ui/select.tsx +39 -0
  276. package/templates/imessage/components/ui/table.tsx +124 -0
  277. package/templates/imessage/components/ui/textarea.tsx +24 -0
  278. package/templates/imessage/components.json +20 -0
  279. package/templates/imessage/functions/answerNow.ts +34 -0
  280. package/templates/imessage/functions/assistant.ts +96 -0
  281. package/templates/imessage/functions/beginTurn.ts +101 -0
  282. package/templates/imessage/functions/cancelReminder.ts +13 -0
  283. package/templates/imessage/functions/claimOutbound.ts +44 -0
  284. package/templates/imessage/functions/clearDemo.ts +18 -0
  285. package/templates/imessage/functions/deleteNote.ts +11 -0
  286. package/templates/imessage/functions/deliverOutbound.ts +55 -0
  287. package/templates/imessage/functions/finishTurn.ts +84 -0
  288. package/templates/imessage/functions/fireReminder.ts +42 -0
  289. package/templates/imessage/functions/ingestInbound.ts +22 -0
  290. package/templates/imessage/functions/ownerAccount.ts +13 -0
  291. package/templates/imessage/functions/processTurn.ts +74 -0
  292. package/templates/imessage/functions/relayApply.ts +102 -0
  293. package/templates/imessage/functions/relaySync.ts +63 -0
  294. package/templates/imessage/functions/releaseOutbound.ts +18 -0
  295. package/templates/imessage/functions/resolveTurn.ts +25 -0
  296. package/templates/imessage/functions/saveContact.ts +27 -0
  297. package/templates/imessage/functions/seedDemo.ts +70 -0
  298. package/templates/imessage/functions/sendOwnerMessage.ts +28 -0
  299. package/templates/imessage/functions/sendblueWebhook.ts +49 -0
  300. package/templates/imessage/functions/setContactStatus.ts +17 -0
  301. package/templates/imessage/functions/settleOutbound.ts +35 -0
  302. package/templates/imessage/functions/setupStatus.ts +33 -0
  303. package/templates/imessage/functions/sweep.ts +58 -0
  304. package/templates/imessage/functions/toolCancelReminder.ts +17 -0
  305. package/templates/imessage/functions/toolForgetNote.ts +15 -0
  306. package/templates/imessage/functions/toolListNotes.ts +16 -0
  307. package/templates/imessage/functions/toolListReminders.ts +17 -0
  308. package/templates/imessage/functions/toolSaveNote.ts +22 -0
  309. package/templates/imessage/functions/toolSetReminder.ts +55 -0
  310. package/templates/imessage/functions/updateSettings.ts +48 -0
  311. package/templates/imessage/gitignore +11 -0
  312. package/templates/imessage/lib/agent-call.ts +251 -0
  313. package/templates/imessage/lib/assistant.ts +74 -0
  314. package/templates/imessage/lib/chunk.ts +135 -0
  315. package/templates/imessage/lib/demo.ts +68 -0
  316. package/templates/imessage/lib/format.ts +170 -0
  317. package/templates/imessage/lib/gate.ts +104 -0
  318. package/templates/imessage/lib/handles.ts +67 -0
  319. package/templates/imessage/lib/provider.ts +38 -0
  320. package/templates/imessage/lib/relay-protocol.ts +95 -0
  321. package/templates/imessage/lib/reminders.ts +41 -0
  322. package/templates/imessage/lib/secrets.ts +59 -0
  323. package/templates/imessage/lib/sendblue.ts +173 -0
  324. package/templates/imessage/lib/store.ts +407 -0
  325. package/templates/imessage/lib/transport.ts +135 -0
  326. package/templates/imessage/lib/utils.ts +10 -0
  327. package/templates/imessage/package.json +40 -0
  328. package/templates/imessage/relay/.env.example +14 -0
  329. package/templates/imessage/relay/applescript.ts +70 -0
  330. package/templates/imessage/relay/chatdb.ts +165 -0
  331. package/templates/imessage/relay/client.ts +41 -0
  332. package/templates/imessage/relay/main.ts +137 -0
  333. package/templates/imessage/relay/state.ts +35 -0
  334. package/templates/imessage/tests/agent-call.test.ts +112 -0
  335. package/templates/imessage/tests/applescript.test.ts +88 -0
  336. package/templates/imessage/tests/chatdb.test.ts +139 -0
  337. package/templates/imessage/tests/chunk.test.ts +61 -0
  338. package/templates/imessage/tests/fake-ctx.ts +88 -0
  339. package/templates/imessage/tests/ingest.test.ts +141 -0
  340. package/templates/imessage/tests/lib.test.ts +99 -0
  341. package/templates/imessage/tests/review-fixes.test.ts +138 -0
  342. package/templates/imessage/tests/secrets.test.ts +36 -0
  343. package/templates/imessage/tests/sendblue.test.ts +143 -0
  344. package/templates/imessage/tests/setup.ts +5 -0
  345. package/templates/imessage/tsconfig.json +18 -0
  346. package/templates/inventory/README.md +21 -0
  347. package/templates/inventory/app/apple-icon.png +0 -0
  348. package/templates/inventory/app/globals.css +29 -14
  349. package/templates/inventory/app/icon.svg +1 -0
  350. package/templates/inventory/app/layout.tsx +7 -5
  351. package/templates/inventory/app/movements/movements-view.tsx +32 -10
  352. package/templates/inventory/app/movements/page.tsx +2 -1
  353. package/templates/inventory/app/page.tsx +4 -6
  354. package/templates/inventory/app/products/[id]/page.tsx +2 -1
  355. package/templates/inventory/app/products/[id]/product-view.tsx +55 -25
  356. package/templates/inventory/app/products-view.tsx +74 -33
  357. package/templates/inventory/app/workspace.tsx +34 -16
  358. package/templates/inventory/app.ts +10 -2
  359. package/templates/inventory/components/app-shell.tsx +94 -0
  360. package/templates/inventory/components/auth-form.tsx +35 -5
  361. package/templates/inventory/components/avatar.tsx +5 -1
  362. package/templates/inventory/components/brand-mark.tsx +25 -0
  363. package/templates/inventory/components/category-tile.tsx +49 -0
  364. package/templates/inventory/components/command-palette.tsx +17 -17
  365. package/templates/inventory/components/data-table.tsx +97 -36
  366. package/templates/inventory/components/filter-tabs.tsx +101 -0
  367. package/templates/inventory/components/nav.tsx +14 -0
  368. package/templates/inventory/components/page-header.tsx +43 -7
  369. package/templates/inventory/components/require-auth.tsx +24 -26
  370. package/templates/inventory/components/sidebar.tsx +54 -48
  371. package/templates/inventory/components/stock-level.tsx +30 -14
  372. package/templates/inventory/components/summary-bar.tsx +8 -15
  373. package/templates/inventory/components/ui/button.tsx +5 -4
  374. package/templates/inventory/components/ui/dialog.tsx +1 -1
  375. package/templates/inventory/components/ui/input.tsx +1 -1
  376. package/templates/inventory/components/ui/select.tsx +1 -1
  377. package/templates/inventory/components/ui/textarea.tsx +1 -1
  378. package/templates/inventory/functions/seedWorkspace.ts +18 -8
  379. package/templates/inventory/lib/brand.ts +9 -0
  380. package/templates/inventory/lib/demo-team.ts +51 -0
  381. package/templates/inventory/lib/search.ts +4 -3
  382. package/templates/inventory/lib/seed.ts +29 -2
  383. package/templates/inventory/lib/stock.ts +32 -0
  384. package/templates/inventory/public/favicon.ico +0 -0
  385. package/templates/inventory/tests/demo-team.test.ts +18 -0
  386. package/templates/inventory/tests/stock.test.ts +29 -0
  387. package/templates/invoices/README.md +16 -0
  388. package/templates/invoices/app/apple-icon.png +0 -0
  389. package/templates/invoices/app/clients/clients-view.tsx +18 -6
  390. package/templates/invoices/app/clients/page.tsx +2 -1
  391. package/templates/invoices/app/globals.css +29 -14
  392. package/templates/invoices/app/icon.svg +1 -0
  393. package/templates/invoices/app/invoices/[id]/invoice-view.tsx +72 -48
  394. package/templates/invoices/app/invoices/[id]/page.tsx +2 -1
  395. package/templates/invoices/app/invoices-view.tsx +81 -32
  396. package/templates/invoices/app/layout.tsx +7 -5
  397. package/templates/invoices/app/page.tsx +4 -6
  398. package/templates/invoices/app/workspace.tsx +26 -16
  399. package/templates/invoices/app.ts +2 -2
  400. package/templates/invoices/components/app-shell.tsx +94 -0
  401. package/templates/invoices/components/auth-form.tsx +35 -5
  402. package/templates/invoices/components/avatar.tsx +5 -1
  403. package/templates/invoices/components/brand-mark.tsx +26 -0
  404. package/templates/invoices/components/command-palette.tsx +17 -17
  405. package/templates/invoices/components/data-table.tsx +97 -36
  406. package/templates/invoices/components/filter-tabs.tsx +101 -0
  407. package/templates/invoices/components/line-items.tsx +19 -14
  408. package/templates/invoices/components/nav.tsx +14 -0
  409. package/templates/invoices/components/page-header.tsx +43 -7
  410. package/templates/invoices/components/require-auth.tsx +24 -26
  411. package/templates/invoices/components/sidebar.tsx +54 -48
  412. package/templates/invoices/components/status-badge.tsx +7 -7
  413. package/templates/invoices/components/summary-bar.tsx +5 -5
  414. package/templates/invoices/components/ui/button.tsx +5 -4
  415. package/templates/invoices/components/ui/dialog.tsx +1 -1
  416. package/templates/invoices/components/ui/input.tsx +1 -1
  417. package/templates/invoices/components/ui/select.tsx +1 -1
  418. package/templates/invoices/components/ui/textarea.tsx +1 -1
  419. package/templates/invoices/functions/recordPayment.ts +3 -0
  420. package/templates/invoices/lib/billing.ts +40 -0
  421. package/templates/invoices/lib/brand.ts +9 -0
  422. package/templates/invoices/lib/search.ts +4 -3
  423. package/templates/invoices/public/favicon.ico +0 -0
  424. package/templates/invoices/tests/billing.test.ts +27 -0
  425. package/templates/ios/consumer/apps/ios/Package.swift +4 -3
  426. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ActivityView.swift +107 -0
  427. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/AppModel.swift +171 -0
  428. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/AuthView.swift +182 -0
  429. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/CommentsView.swift +136 -0
  430. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ComposeView.swift +152 -0
  431. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ExploreView.swift +117 -0
  432. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/FeedView.swift +175 -159
  433. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/MainTabView.swift +54 -0
  434. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Media.swift +271 -0
  435. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Models.swift +101 -4
  436. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/PostCard.swift +245 -0
  437. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileEditorView.swift +208 -0
  438. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileView.swift +183 -0
  439. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/RootView.swift +25 -31
  440. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/SocialStore.swift +285 -0
  441. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/StoryViewer.swift +155 -0
  442. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/Theme.swift +82 -0
  443. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/__APP_NAME_PASCAL__App.swift +4 -47
  444. package/templates/ios/consumer/apps/ios/project.yml +13 -9
  445. package/templates/local-service/.env.example +7 -0
  446. package/templates/local-service/README.md +26 -2
  447. package/templates/local-service/app/(marketing)/booking-widget.tsx +48 -9
  448. package/templates/local-service/app/(marketing)/page.tsx +66 -42
  449. package/templates/local-service/app/auth-form.tsx +8 -8
  450. package/templates/local-service/app/dashboard/dashboard-client.tsx +119 -92
  451. package/templates/local-service/app/dashboard/page.tsx +14 -14
  452. package/templates/local-service/app/icon.svg +2 -0
  453. package/templates/local-service/app/login/page.tsx +15 -15
  454. package/templates/local-service/functions/seedDemo.ts +49 -0
  455. package/templates/local-service/lib/demo.ts +135 -0
  456. package/templates/local-service/lib/hours.ts +44 -0
  457. package/templates/local-service/lib/site.config.ts +8 -3
  458. package/templates/local-service/lib/slots.ts +3 -0
  459. package/templates/local-service/public/favicon.ico +0 -0
  460. package/templates/local-service/tests/booking.test.ts +104 -0
  461. package/templates/marketplace/README.md +23 -15
  462. package/templates/marketplace/app/globals.css +172 -114
  463. package/templates/marketplace/app/layout.tsx +75 -30
  464. package/templates/marketplace/app/listing/[id]/page.tsx +210 -123
  465. package/templates/marketplace/app/me/page.tsx +4 -4
  466. package/templates/marketplace/app/page.tsx +221 -298
  467. package/templates/marketplace/app/sell/page.tsx +8 -11
  468. package/templates/marketplace/app.ts +32 -7
  469. package/templates/marketplace/client/ActivityFeed.tsx +311 -0
  470. package/templates/marketplace/client/AuthNav.tsx +24 -16
  471. package/templates/marketplace/client/ListingCard.tsx +118 -0
  472. package/templates/marketplace/client/LiveGrid.tsx +92 -0
  473. package/templates/marketplace/client/LiveListingStatus.tsx +32 -24
  474. package/templates/marketplace/client/LoginCard.tsx +114 -136
  475. package/templates/marketplace/client/MarketProvider.tsx +3 -5
  476. package/templates/marketplace/client/MyMarket.tsx +371 -185
  477. package/templates/marketplace/client/OfferPanel.tsx +421 -287
  478. package/templates/marketplace/client/SellForm.tsx +271 -192
  479. package/templates/marketplace/client/ThemeToggle.tsx +1 -0
  480. package/templates/marketplace/client/WatchButton.tsx +16 -16
  481. package/templates/marketplace/client/market.ts +61 -14
  482. package/templates/marketplace/functions/seedMarket.ts +143 -36
  483. package/templates/marketplace/functions/seedOffers.ts +101 -0
  484. package/templates/marketplace/lib/catalog.ts +72 -1
  485. package/templates/marketplace/public/images/listings/ceramic-lamp-640.webp +0 -0
  486. package/templates/marketplace/public/images/listings/ceramic-lamp.webp +0 -0
  487. package/templates/marketplace/public/images/listings/duffel-640.webp +0 -0
  488. package/templates/marketplace/public/images/listings/duffel.webp +0 -0
  489. package/templates/marketplace/public/images/listings/film-camera-640.webp +0 -0
  490. package/templates/marketplace/public/images/listings/film-camera.webp +0 -0
  491. package/templates/marketplace/public/images/listings/lounge-chair-640.webp +0 -0
  492. package/templates/marketplace/public/images/listings/lounge-chair.webp +0 -0
  493. package/templates/marketplace/public/images/listings/road-bike-640.webp +0 -0
  494. package/templates/marketplace/public/images/listings/road-bike.webp +0 -0
  495. package/templates/marketplace/public/images/listings/slipper-chair-640.webp +0 -0
  496. package/templates/marketplace/public/images/listings/slipper-chair.webp +0 -0
  497. package/templates/marketplace/public/images/listings/turntable-640.webp +0 -0
  498. package/templates/marketplace/public/images/listings/turntable.webp +0 -0
  499. package/templates/marketplace/public/images/listings/wardrobe-640.webp +0 -0
  500. package/templates/marketplace/public/images/listings/wardrobe.webp +0 -0
  501. package/templates/marketplace/public/images/listings/watch-640.webp +0 -0
  502. package/templates/marketplace/public/images/listings/watch.webp +0 -0
  503. package/templates/marketplace/public/images/listings/weekender-bag-640.webp +0 -0
  504. package/templates/marketplace/public/images/listings/weekender-bag.webp +0 -0
  505. package/templates/marketplace/tests/example.test.ts +64 -2
  506. package/templates/marketplace/tests/listing-card.test.tsx +61 -0
  507. package/templates/projects/README.md +24 -3
  508. package/templates/projects/app/apple-icon.png +0 -0
  509. package/templates/projects/app/clients/clients-view.tsx +20 -6
  510. package/templates/projects/app/clients/page.tsx +2 -1
  511. package/templates/projects/app/globals.css +29 -14
  512. package/templates/projects/app/icon.svg +1 -0
  513. package/templates/projects/app/layout.tsx +7 -5
  514. package/templates/projects/app/page.tsx +3 -5
  515. package/templates/projects/app/projects/[id]/page.tsx +2 -1
  516. package/templates/projects/app/projects/[id]/project-view.tsx +45 -30
  517. package/templates/projects/app/projects-view.tsx +105 -52
  518. package/templates/projects/app/workspace.tsx +41 -20
  519. package/templates/projects/app.ts +2 -2
  520. package/templates/projects/components/app-shell.tsx +94 -0
  521. package/templates/projects/components/auth-form.tsx +35 -5
  522. package/templates/projects/components/avatar.tsx +5 -1
  523. package/templates/projects/components/board-skeleton.tsx +3 -3
  524. package/templates/projects/components/brand-mark.tsx +25 -0
  525. package/templates/projects/components/command-palette.tsx +17 -17
  526. package/templates/projects/components/data-table.tsx +97 -36
  527. package/templates/projects/components/filter-tabs.tsx +101 -0
  528. package/templates/projects/components/meter.tsx +48 -0
  529. package/templates/projects/components/nav.tsx +14 -0
  530. package/templates/projects/components/page-header.tsx +43 -7
  531. package/templates/projects/components/require-auth.tsx +24 -26
  532. package/templates/projects/components/sidebar.tsx +54 -48
  533. package/templates/projects/components/summary-bar.tsx +49 -0
  534. package/templates/projects/components/task-board.tsx +10 -9
  535. package/templates/projects/components/time-dialog.tsx +29 -5
  536. package/templates/projects/components/ui/button.tsx +5 -4
  537. package/templates/projects/components/ui/dialog.tsx +1 -1
  538. package/templates/projects/components/ui/input.tsx +1 -1
  539. package/templates/projects/components/ui/select.tsx +1 -1
  540. package/templates/projects/components/ui/textarea.tsx +1 -1
  541. package/templates/projects/functions/seedWorkspace.ts +26 -12
  542. package/templates/projects/lib/brand.ts +9 -0
  543. package/templates/projects/lib/demo-team.ts +51 -0
  544. package/templates/projects/lib/search.ts +4 -3
  545. package/templates/projects/lib/seed.ts +35 -1
  546. package/templates/projects/lib/work.ts +63 -0
  547. package/templates/projects/public/favicon.ico +0 -0
  548. package/templates/projects/tests/demo-team.test.ts +18 -0
  549. package/templates/projects/tests/work.test.ts +65 -0
  550. package/templates/restaurant/.env.example +7 -0
  551. package/templates/restaurant/README.md +29 -3
  552. package/templates/restaurant/app/(marketing)/layout.tsx +4 -2
  553. package/templates/restaurant/app/(marketing)/page.tsx +47 -23
  554. package/templates/restaurant/app/(marketing)/reservation-widget.tsx +37 -7
  555. package/templates/restaurant/app/auth-form.tsx +8 -8
  556. package/templates/restaurant/app/dashboard/dashboard-client.tsx +241 -109
  557. package/templates/restaurant/app/dashboard/page.tsx +14 -14
  558. package/templates/restaurant/app/icon.svg +4 -0
  559. package/templates/restaurant/app/login/page.tsx +15 -15
  560. package/templates/restaurant/functions/seedDemo.ts +44 -0
  561. package/templates/restaurant/lib/demo.ts +144 -0
  562. package/templates/restaurant/lib/hours.ts +45 -0
  563. package/templates/restaurant/lib/site.config.ts +3 -3
  564. package/templates/restaurant/public/favicon.ico +0 -0
  565. package/templates/restaurant/tests/reservations.test.ts +67 -0
  566. package/templates/saas/README.md +54 -35
  567. package/templates/saas/app/(auth)/auth-form.tsx +25 -23
  568. package/templates/saas/app/(auth)/forgot-password/page.tsx +1 -1
  569. package/templates/saas/app/(auth)/layout.tsx +27 -33
  570. package/templates/saas/app/(auth)/login/page.tsx +1 -1
  571. package/templates/saas/app/(auth)/reset-password/page.tsx +1 -1
  572. package/templates/saas/app/(auth)/signup/page.tsx +1 -1
  573. package/templates/saas/app/(marketing)/layout.tsx +127 -253
  574. package/templates/saas/app/(marketing)/page.tsx +133 -372
  575. package/templates/saas/app/(marketing)/pricing/page.tsx +21 -19
  576. package/templates/saas/app/(marketing)/products/[slug]/page.tsx +40 -95
  577. package/templates/saas/app/dashboard/board-client.tsx +416 -0
  578. package/templates/saas/app/dashboard/dashboard-client.tsx +30 -615
  579. package/templates/saas/app/dashboard/layout.tsx +27 -13
  580. package/templates/saas/app/dashboard/overview-client.tsx +332 -0
  581. package/templates/saas/app/dashboard/page.tsx +29 -35
  582. package/templates/saas/app/dashboard/projects/[id]/page.tsx +29 -0
  583. package/templates/saas/app/dashboard/projects/page.tsx +11 -7
  584. package/templates/saas/app/dashboard/projects-client.tsx +398 -0
  585. package/templates/saas/app/globals.css +5 -4
  586. package/templates/saas/app/icon.svg +1 -0
  587. package/templates/saas/app/onboarding/onboarding-client.tsx +93 -26
  588. package/templates/saas/app/onboarding/page.tsx +6 -2
  589. package/templates/saas/app.ts +68 -13
  590. package/templates/saas/components/dashboard-shell.tsx +212 -132
  591. package/templates/saas/components/marketing.tsx +137 -274
  592. package/templates/saas/components/pricing-table.tsx +12 -11
  593. package/templates/saas/components/setup-checklist.tsx +31 -29
  594. package/templates/saas/components/task-ui.tsx +199 -0
  595. package/templates/saas/functions/createProject.ts +7 -13
  596. package/templates/saas/functions/createTask.ts +67 -0
  597. package/templates/saas/functions/deleteProject.ts +17 -0
  598. package/templates/saas/functions/deleteTask.ts +14 -0
  599. package/templates/saas/functions/seedWorkspace.ts +46 -0
  600. package/templates/saas/functions/setProjectStatus.ts +41 -0
  601. package/templates/saas/functions/updateProfile.ts +13 -0
  602. package/templates/saas/functions/updateProject.ts +4 -5
  603. package/templates/saas/functions/updateTask.ts +88 -0
  604. package/templates/saas/lib/members.ts +53 -0
  605. package/templates/saas/lib/names.ts +53 -0
  606. package/templates/saas/lib/plans.ts +11 -0
  607. package/templates/saas/lib/sample-workspace.ts +117 -0
  608. package/templates/saas/lib/site.config.ts +200 -463
  609. package/templates/saas/lib/tasks.ts +101 -0
  610. package/templates/saas/lib/use-live.ts +25 -0
  611. package/templates/saas/public/favicon.ico +0 -0
  612. package/templates/saas/public/screenshots/board.png +0 -0
  613. package/templates/saas/public/screenshots/members.png +0 -0
  614. package/templates/saas/public/screenshots/overview.png +0 -0
  615. package/templates/saas/public/screenshots/projects.png +0 -0
  616. package/templates/saas/scripts/capture-screenshots.mjs +156 -0
  617. package/templates/saas/tests/names.test.ts +35 -0
  618. package/templates/saas/tests/plans.test.ts +12 -0
  619. package/templates/saas/tests/sample-workspace.test.ts +46 -0
  620. package/templates/saas/tests/tasks.test.ts +81 -0
  621. package/templates/shop/README.md +25 -13
  622. package/templates/shop/app/(marketing)/layout.tsx +94 -67
  623. package/templates/shop/app/(marketing)/not-found.tsx +13 -12
  624. package/templates/shop/app/(marketing)/page.tsx +120 -59
  625. package/templates/shop/app/(marketing)/shop-client.tsx +364 -237
  626. package/templates/shop/app/(marketing)/success/page.tsx +75 -22
  627. package/templates/shop/app/globals.css +94 -1
  628. package/templates/shop/app/layout.tsx +4 -4
  629. package/templates/shop/app/login/page.tsx +4 -4
  630. package/templates/shop/app.ts +18 -6
  631. package/templates/shop/components/cart-button.tsx +33 -0
  632. package/templates/shop/components/marketing.tsx +17 -87
  633. package/templates/shop/components/shelf-count.tsx +36 -0
  634. package/templates/shop/functions/checkout.ts +17 -1
  635. package/templates/shop/lib/cart-store.ts +57 -0
  636. package/templates/shop/lib/shelf-store.ts +35 -0
  637. package/templates/shop/lib/shop.ts +27 -0
  638. package/templates/shop/lib/site.config.ts +108 -98
  639. package/templates/shop/public/images/hero.jpg +0 -0
  640. package/templates/shop/public/images/products/cedar-smoke.jpg +0 -0
  641. package/templates/shop/public/images/products/fig-leaf.jpg +0 -0
  642. package/templates/shop/public/images/products/linen.jpg +0 -0
  643. package/templates/shop/public/images/products/sea-salt.jpg +0 -0
  644. package/templates/shop/public/images/products/tobacco-oak.jpg +0 -0
  645. package/templates/shop/tests/shop.test.ts +64 -0
  646. package/templates/waitlist/.env.example +7 -0
  647. package/templates/waitlist/README.md +29 -13
  648. package/templates/waitlist/app/(marketing)/page.tsx +9 -7
  649. package/templates/waitlist/app/(marketing)/waitlist-hero.tsx +64 -31
  650. package/templates/waitlist/app/auth-form.tsx +8 -8
  651. package/templates/waitlist/app/dashboard/dashboard-client.tsx +132 -95
  652. package/templates/waitlist/app/dashboard/page.tsx +17 -16
  653. package/templates/waitlist/app/icon.svg +2 -0
  654. package/templates/waitlist/app/login/page.tsx +14 -14
  655. package/templates/waitlist/app.ts +6 -6
  656. package/templates/waitlist/functions/joinWaitlist.ts +6 -18
  657. package/templates/waitlist/functions/seedDemo.ts +32 -0
  658. package/templates/waitlist/lib/demo.ts +94 -0
  659. package/templates/waitlist/lib/launch.ts +19 -0
  660. package/templates/waitlist/lib/site.config.ts +14 -9
  661. package/templates/waitlist/lib/stats.ts +35 -0
  662. package/templates/waitlist/public/favicon.ico +0 -0
  663. package/templates/waitlist/tests/counter.test.ts +107 -0
  664. package/templates/waitlist/tests/live-count.test.tsx +48 -0
  665. package/templates/ai-chat/tests/example.test.ts +0 -12
  666. package/templates/backend/consumer/apps/api/functions/feed.ts +0 -57
  667. package/templates/backend/consumer/apps/api/functions/profilePosts.ts +0 -17
  668. package/templates/backend/consumer/apps/api/functions/toggleLike.ts +0 -48
  669. package/templates/backend/consumer/apps/api/schema.ts +0 -143
  670. package/templates/chat/functions/_keep.ts +0 -13
  671. package/templates/chat/tests/example.test.ts +0 -12
  672. package/templates/ios/consumer/apps/ios/Sources/__APP_NAME_PASCAL__/ProfileSetupView.swift +0 -68
  673. package/templates/marketplace/client/LiveTicker.tsx +0 -116
  674. package/templates/marketplace/client/ScrollToListingsLink.tsx +0 -29
  675. package/templates/marketplace/public/images/marketplace-hero.webp +0 -0
@@ -1,15 +1,9 @@
1
1
  import React, { useEffect, useMemo, useRef, useState } from "react";
2
- import { Building2, Plus, Search, User } from "lucide-react";
2
+ import { ArrowRight, FileText, Search } from "lucide-react";
3
3
  import { cn } from "@/lib/utils";
4
4
  import { Kbd } from "@/components/kbd";
5
5
  import { moveSelection, searchItems, type SearchItem } from "@/lib/search";
6
6
 
7
- const TYPE_ICON: Record<SearchItem["type"], React.ReactNode> = {
8
- deal: <Search />,
9
- company: <Building2 />,
10
- contact: <User />,
11
- };
12
-
13
7
  export interface CommandAction {
14
8
  id: string;
15
9
  label: string;
@@ -28,12 +22,18 @@ export function CommandPalette({
28
22
  open,
29
23
  items,
30
24
  actions = [],
25
+ placeholder = "Search…",
26
+ icons = {},
31
27
  onClose,
32
28
  onSelect,
33
29
  }: {
34
30
  open: boolean;
35
31
  items: SearchItem[];
36
32
  actions?: CommandAction[];
33
+ /** Input placeholder naming what can be found, such as "Search deals…". */
34
+ placeholder?: string;
35
+ /** Icon per `SearchItem.type`. Unknown types get a document icon. */
36
+ icons?: Record<string, React.ReactNode>;
37
37
  onClose: () => void;
38
38
  onSelect: (item: SearchItem) => void;
39
39
  }) {
@@ -76,7 +76,7 @@ export function CommandPalette({
76
76
 
77
77
  return (
78
78
  <div
79
- className="fixed inset-0 z-50 flex items-start justify-center bg-black/50 pt-[12vh]"
79
+ className="fixed inset-0 z-50 flex items-start justify-center bg-black/40 px-3 pt-[10vh] md:pt-[14vh]"
80
80
  // Clicking the backdrop dismisses; clicks inside the panel must not.
81
81
  onMouseDown={(event) => {
82
82
  if (event.target === event.currentTarget) onClose();
@@ -85,8 +85,8 @@ export function CommandPalette({
85
85
  <div
86
86
  role="dialog"
87
87
  aria-modal="true"
88
- aria-label="Search"
89
- className="w-full max-w-lg overflow-hidden rounded-xl border border-border bg-popover shadow-2xl"
88
+ aria-label="Command menu"
89
+ className="w-full max-w-xl overflow-hidden rounded-xl border border-border bg-popover shadow-[0_24px_64px_-12px_rgb(0_0_0/0.3)]"
90
90
  onKeyDown={(event) => {
91
91
  if (event.key === "Escape") {
92
92
  event.preventDefault();
@@ -109,14 +109,14 @@ export function CommandPalette({
109
109
  ref={inputRef}
110
110
  value={query}
111
111
  onChange={(event) => setQuery(event.target.value)}
112
- placeholder="Search deals, companies, contacts…"
113
- aria-label="Search deals, companies and contacts"
114
- className="h-11 flex-1 bg-transparent text-[13px] outline-none placeholder:text-muted-foreground"
112
+ placeholder={placeholder}
113
+ aria-label={placeholder.replace(/…$/, "")}
114
+ className="h-12 flex-1 bg-transparent text-base outline-none placeholder:text-muted-foreground md:text-[14px]"
115
115
  />
116
- <Kbd>esc</Kbd>
116
+ <Kbd className="max-md:hidden">esc</Kbd>
117
117
  </div>
118
118
 
119
- <div className="max-h-80 overflow-y-auto p-1.5">
119
+ <div className="max-h-[min(360px,60dvh)] overflow-y-auto p-1.5">
120
120
  {rows.length === 0 ? (
121
121
  <p className="px-3 py-6 text-center text-[12px] text-muted-foreground">
122
122
  No matches for “{query}”
@@ -138,12 +138,12 @@ export function CommandPalette({
138
138
  >
139
139
  {row.kind === "action" ? (
140
140
  <>
141
- <Plus />
141
+ <ArrowRight />
142
142
  <span className="flex-1 truncate">{row.action.label}</span>
143
143
  </>
144
144
  ) : (
145
145
  <>
146
- {TYPE_ICON[row.item.type]}
146
+ {icons[row.item.type] ?? <FileText />}
147
147
  <span className="flex-1 truncate">{row.item.title}</span>
148
148
  {row.item.subtitle ? (
149
149
  <span className="truncate text-[12px] text-muted-foreground">
@@ -8,41 +8,81 @@ export interface ColumnDef<Row> {
8
8
  cell: (row: Row) => React.ReactNode;
9
9
  /** Right-align and tabular-figure a numeric column. */
10
10
  numeric?: boolean;
11
+ /**
12
+ * Hide the column below a breakpoint. Phones keep the first column and the
13
+ * one or two numbers that matter; the rest appear as the screen widens.
14
+ */
15
+ hideBelow?: "sm" | "md" | "lg" | "xl";
16
+ /** Width and other classes, applied to the header and every cell. */
11
17
  className?: string;
12
18
  }
13
19
 
20
+ const HIDE: Record<NonNullable<ColumnDef<unknown>["hideBelow"]>, string> = {
21
+ sm: "hidden sm:table-cell",
22
+ md: "hidden md:table-cell",
23
+ lg: "hidden lg:table-cell",
24
+ xl: "hidden xl:table-cell",
25
+ };
26
+
14
27
  /**
15
- * A dense list view. Rows are 36px so a screenful is a screenful of data, and
16
- * the header sticks while the body scrolls.
28
+ * A dense list view. Rows are 40px on desktop and 48px on touch screens, the
29
+ * header sticks while the body scrolls, and the table uses a fixed layout so
30
+ * column widths come from the column definitions, not the content.
17
31
  *
18
- * Generic and presentational — every view here uses the same one, which is why
19
- * companies and contacts look like the same product.
32
+ * Keyboard: every clickable row is a Tab stop; ↑/↓ (or j/k) move between rows
33
+ * and Enter opens one.
20
34
  */
21
35
  export function DataTable<Row extends { id: string }>({
22
36
  rows,
23
37
  columns,
24
38
  onRowClick,
39
+ loading,
25
40
  empty,
41
+ label,
26
42
  }: {
27
43
  rows: Row[];
28
44
  columns: ColumnDef<Row>[];
29
45
  onRowClick?: (row: Row) => void;
46
+ /** Show placeholder rows while the first sync is in flight. */
47
+ loading?: boolean;
30
48
  empty?: React.ReactNode;
49
+ /** Accessible name for the table. */
50
+ label?: string;
31
51
  }) {
32
- if (rows.length === 0 && empty) return <>{empty}</>;
52
+ if (!loading && rows.length === 0 && empty) return <>{empty}</>;
53
+
54
+ function onRowKey(event: React.KeyboardEvent<HTMLTableRowElement>, row: Row) {
55
+ const key = event.key;
56
+ if (key === "Enter" && onRowClick) {
57
+ event.preventDefault();
58
+ onRowClick(row);
59
+ return;
60
+ }
61
+ const down = key === "ArrowDown" || key === "j";
62
+ const up = key === "ArrowUp" || key === "k";
63
+ if (!down && !up) return;
64
+ event.preventDefault();
65
+ const target = (
66
+ down ? event.currentTarget.nextElementSibling : event.currentTarget.previousElementSibling
67
+ ) as HTMLElement | null;
68
+ target?.focus();
69
+ }
33
70
 
34
71
  return (
35
72
  <div className="min-h-0 flex-1 overflow-auto">
36
- <table className="w-full border-collapse text-[13px]">
37
- <thead className="sticky top-0 z-10 bg-background">
73
+ <table aria-label={label} className="w-full table-fixed border-collapse text-[13px]">
74
+ <thead className="sticky top-0 z-10 bg-background/95 backdrop-blur-sm">
38
75
  <tr className="hairline">
39
- {columns.map((column) => (
76
+ {columns.map((column, index) => (
40
77
  <th
41
78
  key={column.key}
42
79
  scope="col"
43
80
  className={cn(
44
- "h-8 px-4 text-left text-[11px] font-medium text-muted-foreground",
81
+ "h-9 px-3 text-left text-[11px] font-medium uppercase tracking-[0.04em] text-muted-foreground",
82
+ index === 0 && "pl-4 md:pl-5",
83
+ index === columns.length - 1 && "pr-4 md:pr-5",
45
84
  column.numeric && "text-right",
85
+ column.hideBelow && HIDE[column.hideBelow],
46
86
  column.className,
47
87
  )}
48
88
  >
@@ -52,37 +92,58 @@ export function DataTable<Row extends { id: string }>({
52
92
  </tr>
53
93
  </thead>
54
94
  <tbody>
55
- {rows.map((row) => (
56
- <tr
57
- key={row.id}
58
- onClick={onRowClick ? () => onRowClick(row) : undefined}
59
- tabIndex={onRowClick ? 0 : undefined}
60
- onKeyDown={
61
- onRowClick
62
- ? (event) => {
63
- if (event.key === "Enter") onRowClick(row);
64
- }
65
- : undefined
66
- }
67
- className={cn(
68
- "border-b border-border/60 transition-colors",
69
- onRowClick && "cursor-pointer hover:bg-surface-1",
70
- )}
71
- >
72
- {columns.map((column) => (
73
- <td
74
- key={column.key}
95
+ {loading
96
+ ? Array.from({ length: 8 }).map((_, index) => (
97
+ <tr key={`skeleton-${index}`} aria-hidden="true" className="border-b border-border/60">
98
+ {columns.map((column, c) => (
99
+ <td
100
+ key={column.key}
101
+ className={cn(
102
+ "h-12 px-3 md:h-10",
103
+ c === 0 && "pl-4 md:pl-5",
104
+ column.hideBelow && HIDE[column.hideBelow],
105
+ column.className,
106
+ )}
107
+ >
108
+ <div
109
+ className={cn(
110
+ "h-2.5 animate-pulse rounded-full bg-foreground/[0.07]",
111
+ column.numeric ? "ml-auto w-10" : c === 0 ? "w-3/4" : "w-1/2",
112
+ )}
113
+ />
114
+ </td>
115
+ ))}
116
+ </tr>
117
+ ))
118
+ : rows.map((row) => (
119
+ <tr
120
+ key={row.id}
121
+ onClick={onRowClick ? () => onRowClick(row) : undefined}
122
+ tabIndex={onRowClick ? 0 : undefined}
123
+ onKeyDown={onRowClick ? (event) => onRowKey(event, row) : undefined}
75
124
  className={cn(
76
- "h-9 max-w-0 truncate px-4",
77
- column.numeric && "tabular text-right",
78
- column.className,
125
+ "border-b border-border/60 transition-colors",
126
+ onRowClick &&
127
+ "cursor-pointer hover:bg-foreground/[0.025] focus-visible:bg-primary/[0.06] focus-visible:outline-none",
79
128
  )}
80
129
  >
81
- {column.cell(row)}
82
- </td>
130
+ {columns.map((column, index) => (
131
+ <td
132
+ key={column.key}
133
+ className={cn(
134
+ "h-12 truncate px-3 md:h-10",
135
+ index === 0 && "pl-4 md:pl-5",
136
+ index === columns.length - 1 && "pr-4 md:pr-5",
137
+ column.numeric && "tabular text-right",
138
+ column.hideBelow && HIDE[column.hideBelow],
139
+ column.className,
140
+ )}
141
+ >
142
+ {column.cell(row)}
143
+ </td>
144
+ ))}
145
+ </tr>
83
146
  ))}
84
- </tr>
85
- ))}
86
147
  </tbody>
87
148
  </table>
88
149
  </div>
@@ -0,0 +1,101 @@
1
+ import React from "react";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ export interface FilterTab {
5
+ id: string;
6
+ label: string;
7
+ count?: number;
8
+ }
9
+
10
+ /**
11
+ * A row of view filters under the page header, each with its count. On a
12
+ * phone the row scrolls sideways inside itself instead of widening the page.
13
+ *
14
+ * Each filter is a toggle button in a labelled group; ←/→ move between them
15
+ * and Home/End jump to the ends.
16
+ */
17
+ export function FilterTabs({
18
+ tabs,
19
+ value,
20
+ onChange,
21
+ label,
22
+ trailing,
23
+ className,
24
+ }: {
25
+ tabs: FilterTab[];
26
+ value: string;
27
+ onChange: (id: string) => void;
28
+ /** Accessible name for the group, such as "Ticket status". */
29
+ label: string;
30
+ /** Extra controls at the end of the row, such as a toggle. */
31
+ trailing?: React.ReactNode;
32
+ className?: string;
33
+ }) {
34
+ function onKeyDown(event: React.KeyboardEvent<HTMLButtonElement>, index: number) {
35
+ const target =
36
+ event.key === "ArrowRight"
37
+ ? (index + 1) % tabs.length
38
+ : event.key === "ArrowLeft"
39
+ ? (index - 1 + tabs.length) % tabs.length
40
+ : event.key === "Home"
41
+ ? 0
42
+ : event.key === "End"
43
+ ? tabs.length - 1
44
+ : -1;
45
+ if (target < 0) return;
46
+ event.preventDefault();
47
+ const next = tabs[target];
48
+ onChange(next.id);
49
+ const list = event.currentTarget.parentElement;
50
+ list?.querySelector<HTMLButtonElement>(`[data-tab="${next.id}"]`)?.focus();
51
+ }
52
+
53
+ return (
54
+ <div
55
+ className={cn(
56
+ "flex h-11 shrink-0 items-center gap-3 border-b border-border px-3 md:px-5",
57
+ className,
58
+ )}
59
+ >
60
+ <div
61
+ role="group"
62
+ aria-label={label}
63
+ className="-mx-1 flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto px-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
64
+ >
65
+ {tabs.map((tab, index) => {
66
+ const selected = tab.id === value;
67
+ return (
68
+ <button
69
+ key={tab.id}
70
+ type="button"
71
+ data-tab={tab.id}
72
+ aria-pressed={selected}
73
+ tabIndex={selected ? 0 : -1}
74
+ onClick={() => onChange(tab.id)}
75
+ onKeyDown={(event) => onKeyDown(event, index)}
76
+ className={cn(
77
+ "flex h-7 shrink-0 items-center gap-1.5 rounded-md px-2.5 text-[12.5px] transition-colors",
78
+ selected
79
+ ? "bg-foreground/[0.07] font-medium text-foreground"
80
+ : "text-muted-foreground hover:bg-foreground/[0.04] hover:text-foreground",
81
+ )}
82
+ >
83
+ {tab.label}
84
+ {typeof tab.count === "number" ? (
85
+ <span
86
+ className={cn(
87
+ "tabular text-[11.5px]",
88
+ selected ? "text-foreground/60" : "text-muted-foreground/80",
89
+ )}
90
+ >
91
+ {tab.count}
92
+ </span>
93
+ ) : null}
94
+ </button>
95
+ );
96
+ })}
97
+ </div>
98
+ {trailing ? <div className="flex shrink-0 items-center gap-2">{trailing}</div> : null}
99
+ </div>
100
+ );
101
+ }
@@ -76,20 +76,20 @@ export function LineItems({
76
76
  );
77
77
 
78
78
  return (
79
- <div className="rounded-lg border border-border bg-card">
79
+ <div className="overflow-hidden rounded-xl border border-border bg-card">
80
80
  <table className="w-full border-collapse text-[13px]">
81
81
  <thead>
82
82
  <tr className="hairline">
83
- <th scope="col" className="h-8 px-3 text-left text-[11px] font-medium text-muted-foreground">
83
+ <th scope="col" className="h-9 px-3.5 text-left text-[11px] font-medium uppercase tracking-[0.04em] text-muted-foreground">
84
84
  Description
85
85
  </th>
86
- <th scope="col" className="h-8 w-20 px-3 text-right text-[11px] font-medium text-muted-foreground">
86
+ <th scope="col" className="hidden h-9 w-20 px-3 text-right text-[11px] font-medium uppercase tracking-[0.04em] text-muted-foreground sm:table-cell">
87
87
  Qty
88
88
  </th>
89
- <th scope="col" className="h-8 w-28 px-3 text-right text-[11px] font-medium text-muted-foreground">
89
+ <th scope="col" className="hidden h-9 w-28 px-3 text-right text-[11px] font-medium uppercase tracking-[0.04em] text-muted-foreground sm:table-cell">
90
90
  Unit
91
91
  </th>
92
- <th scope="col" className="h-8 w-28 px-3 text-right text-[11px] font-medium text-muted-foreground">
92
+ <th scope="col" className="h-9 w-28 px-3.5 text-right text-[11px] font-medium uppercase tracking-[0.04em] text-muted-foreground">
93
93
  Amount
94
94
  </th>
95
95
  {editable ? <th className="w-10" /> : null}
@@ -108,14 +108,19 @@ export function LineItems({
108
108
  ) : (
109
109
  ordered.map((item) => (
110
110
  <tr key={item.id} className="border-b border-border/60 last:border-0">
111
- <td className="px-3 py-2">{item.description}</td>
112
- <td className="tabular px-3 py-2 text-right text-muted-foreground">
111
+ <td className="px-3.5 py-2.5">
112
+ {item.description}
113
+ <span className="tabular block text-[12px] text-muted-foreground sm:hidden">
114
+ {quantity(item.quantityMilli)} × {money(item.unitPriceCents)}
115
+ </span>
116
+ </td>
117
+ <td className="tabular hidden px-3 py-2.5 text-right text-muted-foreground sm:table-cell">
113
118
  {quantity(item.quantityMilli)}
114
119
  </td>
115
- <td className="tabular px-3 py-2 text-right text-muted-foreground">
120
+ <td className="tabular hidden px-3 py-2.5 text-right text-muted-foreground sm:table-cell">
116
121
  {money(item.unitPriceCents)}
117
122
  </td>
118
- <td className="tabular px-3 py-2 text-right">
123
+ <td className="tabular px-3.5 py-2.5 text-right font-medium">
119
124
  {money(lineTotalCents(item))}
120
125
  </td>
121
126
  {editable ? (
@@ -138,20 +143,20 @@ export function LineItems({
138
143
  </table>
139
144
 
140
145
  {editable ? (
141
- <form onSubmit={add} className="flex items-end gap-2 border-t border-border p-2">
146
+ <form onSubmit={add} className="flex flex-wrap items-end gap-2 border-t border-border bg-surface-1 p-2.5">
142
147
  <Input
143
148
  aria-label="Description"
144
149
  placeholder="Senior engineering"
145
150
  value={description}
146
151
  onChange={(event) => setDescription(event.target.value)}
147
- className="h-8 flex-1"
152
+ className="h-9 min-w-[12rem] flex-1 bg-background md:h-8"
148
153
  />
149
154
  <Input
150
155
  aria-label="Quantity"
151
156
  inputMode="decimal"
152
157
  value={qty}
153
158
  onChange={(event) => setQty(event.target.value)}
154
- className="h-8 w-20 text-right"
159
+ className="h-9 w-20 bg-background text-right md:h-8"
155
160
  />
156
161
  <Input
157
162
  aria-label="Unit price"
@@ -159,9 +164,9 @@ export function LineItems({
159
164
  placeholder="165.00"
160
165
  value={price}
161
166
  onChange={(event) => setPrice(event.target.value)}
162
- className="h-8 w-28 text-right"
167
+ className="h-9 w-28 flex-1 bg-background text-right sm:flex-none md:h-8"
163
168
  />
164
- <Button type="submit" size="sm" disabled={!canAdd} className="h-8">
169
+ <Button type="submit" size="sm" disabled={!canAdd} className="h-9 md:h-8">
165
170
  <Plus />
166
171
  Add
167
172
  </Button>
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { FileText, Users } from "lucide-react";
3
+
4
+ export interface NavEntry {
5
+ href: string;
6
+ label: string;
7
+ icon: React.ReactNode;
8
+ }
9
+
10
+ /** The sidebar's links, top to bottom. Add a view here to put it in the nav. */
11
+ export const NAV: NavEntry[] = [
12
+ { href: "/", label: "Invoices", icon: <FileText /> },
13
+ { href: "/clients", label: "Clients", icon: <Users /> },
14
+ ];
@@ -1,36 +1,72 @@
1
+ "use client";
2
+
1
3
  import React from "react";
4
+ import { Menu, Search } from "lucide-react";
2
5
  import { cn } from "@/lib/utils";
6
+ import { useShell } from "@/components/app-shell";
3
7
 
4
8
  /**
5
9
  * The bar at the top of every view: title on the left, actions on the right.
6
- * Fixed height so switching pages doesn't shift the content below it.
10
+ * Fixed height, so switching pages doesn't shift the content below it.
11
+ *
12
+ * Below the `md` breakpoint it also carries the menu button that opens the
13
+ * navigation drawer and a search button, since the sidebar is hidden there.
7
14
  */
8
15
  export function PageHeader({
9
16
  title,
10
17
  count,
18
+ leading,
11
19
  children,
12
20
  className,
13
21
  }: {
14
22
  title: string;
15
- /** Shown beside the title — the number of rows in view. */
23
+ /** Shown beside the title. Pass the same number the sidebar shows. */
16
24
  count?: number;
25
+ /** Rendered before the title, such as a back link on a detail page. */
26
+ leading?: React.ReactNode;
17
27
  children?: React.ReactNode;
18
28
  className?: string;
19
29
  }) {
30
+ const shell = useShell();
20
31
  return (
21
32
  <header
22
33
  className={cn(
23
- "flex h-12 shrink-0 items-center justify-between gap-3 border-b border-border px-4",
34
+ "flex h-13 shrink-0 items-center justify-between gap-2 border-b border-border px-3 md:gap-3 md:px-5",
24
35
  className,
25
36
  )}
26
37
  >
27
- <div className="flex min-w-0 items-baseline gap-2">
28
- <h1 className="truncate text-[13px] font-semibold">{title}</h1>
38
+ <div className="flex min-w-0 items-center gap-1.5">
39
+ {shell ? (
40
+ <button
41
+ type="button"
42
+ onClick={shell.openNav}
43
+ aria-label="Open navigation"
44
+ className="-ml-1 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-foreground/[0.05] hover:text-foreground md:hidden"
45
+ >
46
+ <Menu className="size-[18px]" />
47
+ </button>
48
+ ) : null}
49
+ {leading}
50
+ <h1 className="truncate text-[14px] font-semibold tracking-[-0.01em]">{title}</h1>
29
51
  {typeof count === "number" ? (
30
- <span className="tabular text-[12px] text-muted-foreground">{count}</span>
52
+ <span className="tabular ml-0.5 rounded-full bg-foreground/[0.06] px-1.5 py-px text-[11.5px] font-medium text-muted-foreground">
53
+ {count}
54
+ </span>
55
+ ) : null}
56
+ </div>
57
+ <div className="flex shrink-0 items-center gap-1.5 md:gap-2">
58
+ {shell ? (
59
+ <button
60
+ type="button"
61
+ onClick={shell.openCommand}
62
+ aria-label="Search"
63
+ className="rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-foreground/[0.05] hover:text-foreground md:hidden"
64
+ >
65
+ <Search className="size-[18px]" />
66
+ </button>
31
67
  ) : null}
68
+ {children}
32
69
  </div>
33
- <div className="flex items-center gap-2">{children}</div>
34
70
  </header>
35
71
  );
36
72
  }
@@ -1,8 +1,10 @@
1
1
  "use client";
2
2
 
3
- import React from "react";
3
+ import React, { useState } from "react";
4
4
  import { useAuth } from "@pylonsync/client";
5
- import { AuthForm } from "@/components/auth-form";
5
+ import { BRAND } from "@/lib/brand";
6
+ import { AuthForm, type AuthMode } from "@/components/auth-form";
7
+ import { BrandMark } from "@/components/brand-mark";
6
8
 
7
9
  /**
8
10
  * Client-side auth gate.
@@ -18,44 +20,40 @@ import { AuthForm } from "@/components/auth-form";
18
20
  * It also removes a full page load from the sign-in path: authenticating swaps
19
21
  * this component's children in place instead of navigating.
20
22
  */
21
- export function RequireAuth({
22
- title,
23
- description,
24
- children,
25
- }: {
26
- title: string;
27
- description: string;
28
- children: React.ReactNode;
29
- }) {
23
+ export function RequireAuth({ children }: { children: React.ReactNode }) {
30
24
  const { isSignedIn, isLoaded } = useAuth();
25
+ const [mode, setMode] = useState<AuthMode>("login");
31
26
 
32
27
  // `isLoaded` covers the beat before the engine has resolved the stored token.
33
28
  // Rendering the form during it would flash a sign-in screen at someone who is
34
29
  // already signed in.
35
30
  if (!isLoaded) {
36
31
  return (
37
- <main className="flex min-h-screen items-center justify-center">
38
- <span className="text-[13px] text-muted-foreground">Loading…</span>
32
+ <main className="flex min-h-dvh items-center justify-center" aria-busy="true">
33
+ <BrandMark className="size-8 animate-pulse" />
34
+ <span className="sr-only">Loading {BRAND.name}</span>
39
35
  </main>
40
36
  );
41
37
  }
42
38
 
43
39
  if (!isSignedIn) {
44
40
  return (
45
- <main className="flex min-h-screen items-center justify-center px-6">
46
- <div className="w-full max-w-[320px]">
47
- <div className="mb-7 flex items-center gap-2">
48
- <span className="flex size-7 items-center justify-center rounded-md bg-primary text-[12px] font-bold text-primary-foreground">
49
- {title.slice(0, 1).toUpperCase()}
50
- </span>
51
- <span className="text-[15px] font-semibold tracking-tight">{title}</span>
41
+ <main className="flex min-h-dvh items-center justify-center bg-surface-1 px-4 py-10">
42
+ <div className="w-full max-w-[380px]">
43
+ <div className="mb-6 flex items-center justify-center gap-2.5">
44
+ <BrandMark className="size-8 rounded-[9px]" />
45
+ <span className="text-[17px] font-semibold tracking-[-0.015em]">{BRAND.name}</span>
52
46
  </div>
53
- <h1 className="text-[19px] font-semibold tracking-tight">
54
- Sign in to your workspace
55
- </h1>
56
- <p className="mt-1 text-[13px] text-muted-foreground">{description}</p>
57
- <div className="mt-6">
58
- <AuthForm />
47
+ <div className="rounded-xl border border-border bg-background p-6 shadow-[0_1px_2px_rgb(0_0_0/0.04),0_12px_32px_-12px_rgb(0_0_0/0.12)] sm:p-7">
48
+ <h1 className="text-[18px] font-semibold tracking-[-0.015em]">
49
+ {mode === "login" ? `Sign in to ${BRAND.name}` : `Create your ${BRAND.name} account`}
50
+ </h1>
51
+ <p className="mt-1.5 text-[13px] leading-5 text-muted-foreground">
52
+ {BRAND.description}
53
+ </p>
54
+ <div className="mt-6">
55
+ <AuthForm mode={mode} onModeChange={setMode} />
56
+ </div>
59
57
  </div>
60
58
  </div>
61
59
  </main>