@pylonsync/create-pylon 0.19.0 → 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,92 +1,14 @@
1
1
  import React from "react";
2
2
  import { Link } from "@pylonsync/react";
3
+ import { ArrowRight, Check } from "lucide-react";
3
4
  import type { SitePage, Comparison } from "@/lib/site";
5
+ import { siteConfig } from "@/lib/site.config";
4
6
 
5
- // Reusable presentational pieces for the marketing pages (homepage +
6
- // /products/[slug]). All server-rendered — no client JS. Restyle here and every
7
- // marketing page follows.
7
+ // Presentational pieces for the marketing pages. All server-rendered, no
8
+ // client JS. Restyle here and every marketing page follows.
8
9
 
9
- // Shared container: the whole marketing site is a contained, left-aligned column.
10
- export const WRAP = "mx-auto w-full max-w-5xl px-6";
11
-
12
- export function Divider() {
13
- return (
14
- <div className={WRAP}>
15
- <div className="border-t border-zinc-200/70" />
16
- </div>
17
- );
18
- }
19
-
20
- export function Eyebrow({ children }: { children: React.ReactNode }) {
21
- return (
22
- <p className="font-mono text-[11px] font-semibold uppercase tracking-[0.14em] text-brand">
23
- {children}
24
- </p>
25
- );
26
- }
27
-
28
- export function Badge({ children }: { children: React.ReactNode }) {
29
- return (
30
- <span className="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white py-1 pl-1 pr-3 text-[13px] text-zinc-600">
31
- <span className="rounded-full bg-brand-soft px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-brand">
32
- New
33
- </span>
34
- {children}
35
- </span>
36
- );
37
- }
38
-
39
- export function SectionHead({
40
- eyebrow,
41
- title,
42
- body,
43
- arrow,
44
- }: {
45
- eyebrow: string;
46
- title: string;
47
- body: string;
48
- arrow?: boolean;
49
- }) {
50
- return (
51
- <div>
52
- <Eyebrow>
53
- {eyebrow}
54
- {arrow ? " →" : ""}
55
- </Eyebrow>
56
- <h2 className="mt-4 max-w-2xl text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
57
- {title}
58
- </h2>
59
- <p className="mt-5 max-w-xl text-[15px] leading-relaxed text-zinc-500">
60
- {body}
61
- </p>
62
- </div>
63
- );
64
- }
65
-
66
- export function FeatureGrid({
67
- items,
68
- columns = 3,
69
- className = "",
70
- }: {
71
- items: { title: string; body: string }[];
72
- columns?: 2 | 3;
73
- className?: string;
74
- }) {
75
- const cols =
76
- columns === 2 ? "sm:grid-cols-2" : "sm:grid-cols-2 lg:grid-cols-3";
77
- return (
78
- <div className={`grid gap-x-8 gap-y-10 ${cols} ${className}`}>
79
- {items.map((f) => (
80
- <div key={f.title}>
81
- <h3 className="text-[15px] font-medium text-brand">{f.title}</h3>
82
- <p className="mt-2 text-[14px] leading-relaxed text-zinc-500">
83
- {f.body}
84
- </p>
85
- </div>
86
- ))}
87
- </div>
88
- );
89
- }
10
+ // Shared container for the marketing site.
11
+ export const WRAP = "mx-auto w-full max-w-6xl px-4 sm:px-6";
90
12
 
91
13
  export function PrimaryButton({
92
14
  href,
@@ -100,122 +22,121 @@ export function PrimaryButton({
100
22
  return (
101
23
  <Link
102
24
  href={href}
103
- className={`inline-flex items-center rounded-full bg-zinc-900 px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-zinc-700 ${className}`}
25
+ className={`group inline-flex h-10 items-center gap-2 rounded-full bg-zinc-950 pl-5 pr-4 text-[14px] font-medium text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_1px_2px_rgba(0,0,0,0.2)] transition-[background-color,transform] duration-200 ease-[cubic-bezier(0.32,0.72,0,1)] hover:bg-zinc-800 active:scale-[0.98] ${className}`}
104
26
  >
105
27
  {children}
28
+ <ArrowRight className="size-4 transition-transform duration-300 ease-[cubic-bezier(0.32,0.72,0,1)] group-hover:translate-x-0.5" />
106
29
  </Link>
107
30
  );
108
31
  }
109
32
 
110
- export function GhostLink({
111
- href,
112
- children,
113
- }: {
114
- href: string;
115
- children: React.ReactNode;
116
- }) {
33
+ export function SecondaryButton({ href, children }: { href: string; children: React.ReactNode }) {
117
34
  return (
118
35
  <Link
119
36
  href={href}
120
- className="text-sm font-medium text-zinc-700 transition-colors hover:text-zinc-900"
37
+ className="inline-flex h-10 items-center rounded-full px-4 text-[14px] font-medium text-zinc-700 ring-1 ring-zinc-200 transition-colors hover:bg-zinc-50 hover:text-zinc-950"
121
38
  >
122
39
  {children}
123
40
  </Link>
124
41
  );
125
42
  }
126
43
 
127
- // Browser-chrome frame around an image placeholder. Drop a real screenshot in
128
- // place of the dashed box.
129
- export function Shot({ url, label }: { url: string; label: string }) {
44
+ /** A region of a 1440x900 screenshot, as fractions of its width and height. */
45
+ export type ShotCrop = {
46
+ left: number;
47
+ top: number;
48
+ width: number;
49
+ /** Width / height of the visible region. */
50
+ ratio: number;
51
+ };
52
+
53
+ /**
54
+ * A product screenshot in a two-layer frame: a tinted outer tray and the
55
+ * image inside it with its own hairline. `crop` shows one region of the
56
+ * full-screen capture, scaled to fill the frame.
57
+ */
58
+ export function ProductShot({
59
+ src,
60
+ alt,
61
+ crop,
62
+ priority = false,
63
+ className = "",
64
+ }: {
65
+ src: string;
66
+ alt: string;
67
+ crop?: ShotCrop;
68
+ priority?: boolean;
69
+ className?: string;
70
+ }) {
71
+ // Screenshots are 1440x900 CSS pixels (captured at 2x).
72
+ const IMAGE_RATIO = 1440 / 900;
130
73
  return (
131
- <div className="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-[0_30px_70px_-35px_rgba(0,0,0,0.3)]">
132
- <div className="flex items-center gap-1.5 border-b border-zinc-100 px-4 py-3">
133
- <span className="size-2.5 rounded-full bg-zinc-200" />
134
- <span className="size-2.5 rounded-full bg-zinc-200" />
135
- <span className="size-2.5 rounded-full bg-zinc-200" />
136
- <span className="mx-auto rounded-md bg-zinc-100 px-10 py-1 text-[11px] text-zinc-400">
137
- {url}
138
- </span>
139
- </div>
140
- <div className="grid aspect-[16/9] place-items-center bg-zinc-50">
141
- <div className="flex flex-col items-center gap-2.5 text-zinc-400">
142
- <span className="flex size-11 items-center justify-center rounded-xl border-2 border-dashed border-zinc-300 text-lg">
143
- ▦
144
- </span>
145
- <p className="text-sm font-medium text-zinc-500">{label}</p>
146
- <p className="text-xs text-zinc-400">Replace with a screenshot</p>
147
- </div>
74
+ <div
75
+ className={`rounded-[18px] bg-zinc-950/[0.035] p-1.5 ring-1 ring-zinc-950/[0.06] sm:rounded-[22px] sm:p-2 ${className}`}
76
+ >
77
+ <div
78
+ className="overflow-hidden rounded-[13px] bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.06),0_24px_48px_-24px_rgba(24,24,60,0.25)] sm:rounded-[15px]"
79
+ style={{ aspectRatio: crop ? crop.ratio : IMAGE_RATIO }}
80
+ >
81
+ <img
82
+ src={src}
83
+ alt={alt}
84
+ loading={priority ? "eager" : "lazy"}
85
+ decoding="async"
86
+ width={1440}
87
+ height={900}
88
+ className="block h-auto max-w-none"
89
+ style={
90
+ crop
91
+ ? {
92
+ width: `${100 / crop.width}%`,
93
+ // Percentage margins resolve against the frame's WIDTH, so
94
+ // the top offset is converted from image-height units.
95
+ marginLeft: `-${(crop.left / crop.width) * 100}%`,
96
+ marginTop: `-${(crop.top / crop.width / IMAGE_RATIO) * 100}%`,
97
+ }
98
+ : { width: "100%" }
99
+ }
100
+ />
148
101
  </div>
149
102
  </div>
150
103
  );
151
104
  }
152
105
 
153
- // Square media slot for a testimonial portrait. Renders the person's initials
154
- // on a soft gradient so it looks intentional out of the box — drop in a real
155
- // photo (an <img> here) when you have one.
156
- export function Portrait({ name }: { name?: string }) {
157
- const initials = name
158
- ? name
159
- .split(/\s+/)
160
- .map((w) => w[0])
161
- .join("")
162
- .slice(0, 2)
163
- .toUpperCase()
164
- : null;
106
+ export function FeatureList({ items }: { items: { title: string; body: string }[] }) {
165
107
  return (
166
- <div className="grid aspect-square w-full place-items-center overflow-hidden rounded-2xl border border-zinc-200 bg-gradient-to-br from-zinc-100 to-zinc-200/80">
167
- {initials ? (
168
- <span className="select-none text-5xl font-semibold tracking-tight text-zinc-400">
169
- {initials}
170
- </span>
171
- ) : (
172
- <span className="flex size-12 items-center justify-center rounded-full border-2 border-dashed border-zinc-300 text-xl text-zinc-400">
173
- ◐
174
- </span>
175
- )}
176
- </div>
108
+ <ul className="grid gap-x-8 gap-y-5 sm:grid-cols-2">
109
+ {items.map((f) => (
110
+ <li key={f.title} className="flex gap-3">
111
+ <span className="mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full bg-brand-soft text-brand">
112
+ <Check className="size-3" strokeWidth={2.5} />
113
+ </span>
114
+ <span>
115
+ <span className="block text-[14px] font-medium text-zinc-900">{f.title}</span>
116
+ <span className="mt-0.5 block text-[13.5px] leading-relaxed text-zinc-500">{f.body}</span>
117
+ </span>
118
+ </li>
119
+ ))}
120
+ </ul>
177
121
  );
178
122
  }
179
123
 
180
- export function Terminal() {
124
+ function PageHero({ title, summary, ctaHref }: { title: string; summary: string; ctaHref: string }) {
181
125
  return (
182
- <div className="overflow-hidden rounded-2xl border border-zinc-800 bg-zinc-950 shadow-[0_30px_70px_-35px_rgba(0,0,0,0.6)]">
183
- <div className="flex items-center gap-1.5 border-b border-white/10 px-4 py-3">
184
- <span className="size-2.5 rounded-full bg-white/20" />
185
- <span className="size-2.5 rounded-full bg-white/20" />
186
- <span className="size-2.5 rounded-full bg-white/20" />
187
- <span className="ml-3 font-mono text-[11px] text-white/40">
188
- acme · automation run
189
- </span>
190
- </div>
191
- <div className="space-y-3 p-6 font-mono text-[12.5px] leading-relaxed text-zinc-300">
192
- <p className="text-zinc-500">▸ Rule · when a task is moved to Done</p>
193
- <p className="text-brand">
194
- step 1{" "}
195
- <span className="text-zinc-500">→ notify the project channel</span>
196
- </p>
197
- <p className="text-brand">
198
- step 2{" "}
199
- <span className="text-zinc-500">→ close the linked subtasks</span>
200
- </p>
201
- <div className="rounded-lg border-l-2 border-brand/60 bg-white/5 px-4 py-3 text-zinc-200">
202
- <p className="font-semibold">Run complete</p>
203
- <p className="mt-1 text-zinc-400">
204
- 2 steps ran in 240ms — 1 notification sent, 3 subtasks closed.
205
- </p>
206
- </div>
207
- <p className="text-zinc-500">▸ Trigger · on every status change</p>
208
- <p className="text-brand">
209
- status{" "}
210
- <span className="text-zinc-500">→ active · 128 runs this week</span>
211
- </p>
126
+ <section className={`${WRAP} pb-16 pt-16 sm:pt-24`}>
127
+ <h1 className="max-w-3xl text-balance text-[2.5rem] font-semibold leading-[1.05] tracking-[-0.035em] text-zinc-950 sm:text-[3.25rem]">
128
+ {title}
129
+ </h1>
130
+ <p className="mt-5 max-w-xl text-[17px] leading-relaxed text-zinc-500">{summary}</p>
131
+ <div className="mt-8">
132
+ <PrimaryButton href={ctaHref}>Get started</PrimaryButton>
212
133
  </div>
213
- </div>
134
+ </section>
214
135
  );
215
136
  }
216
137
 
217
- // A generic content page (solutions / resources / company). Renders a hero, a
218
- // grid of sections, a CTA, and links to its siblings.
138
+ // A generic content page (solutions / resources / company): heading, a grid
139
+ // of sections, and links to its siblings.
219
140
  export function ContentPage({
220
141
  page,
221
142
  siblings,
@@ -230,57 +151,35 @@ export function ContentPage({
230
151
  const others = siblings.filter((s) => s.slug !== page.slug);
231
152
  return (
232
153
  <div className="bg-white text-zinc-900">
233
- <section className={`${WRAP} pt-16 pb-16 sm:pt-20`}>
234
- <Link
235
- href="/"
236
- className="text-[13px] text-zinc-500 transition-colors hover:text-zinc-900"
237
- >
238
- ← Home
239
- </Link>
240
- <div className="mt-6">
241
- <Eyebrow>{page.eyebrow}</Eyebrow>
242
- </div>
243
- <h1 className="mt-4 max-w-2xl text-balance text-[2.25rem] font-semibold leading-[1.05] tracking-[-0.02em] sm:text-[3rem]">
244
- {page.title}
245
- </h1>
246
- <p className="mt-6 max-w-xl text-[17px] leading-relaxed text-zinc-500">
247
- {page.summary}
248
- </p>
249
- <div className="mt-8">
250
- <PrimaryButton href={ctaHref}>Get started</PrimaryButton>
154
+ <PageHero title={page.title} summary={page.summary} ctaHref={ctaHref} />
155
+ <section className={`${WRAP} pb-20`}>
156
+ <div className="grid gap-px overflow-hidden rounded-2xl bg-zinc-200/70 ring-1 ring-zinc-200/70 sm:grid-cols-3">
157
+ {page.sections.map((s) => (
158
+ <div key={s.title} className="bg-white p-6">
159
+ <h2 className="text-[15px] font-semibold text-zinc-900">{s.title}</h2>
160
+ <p className="mt-2 text-[14px] leading-relaxed text-zinc-500">{s.body}</p>
161
+ </div>
162
+ ))}
251
163
  </div>
164
+ {others.length > 0 ? (
165
+ <div className="mt-10 flex flex-wrap gap-2">
166
+ {others.map((s) => (
167
+ <Link
168
+ key={s.slug}
169
+ href={`${basePath}/${s.slug}`}
170
+ className="rounded-full px-3.5 py-1.5 text-[13px] font-medium text-zinc-600 ring-1 ring-zinc-200 transition-colors hover:bg-zinc-50 hover:text-zinc-950"
171
+ >
172
+ {s.navLabel}
173
+ </Link>
174
+ ))}
175
+ </div>
176
+ ) : null}
252
177
  </section>
253
-
254
- <Divider />
255
- <section className={`${WRAP} py-20`}>
256
- <FeatureGrid items={page.sections} />
257
- </section>
258
-
259
- {others.length > 0 && (
260
- <>
261
- <Divider />
262
- <section className={`${WRAP} py-16`}>
263
- <Eyebrow>{page.eyebrow}</Eyebrow>
264
- <div className="mt-6 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
265
- {others.map((s) => (
266
- <Link
267
- key={s.slug}
268
- href={`${basePath}/${s.slug}`}
269
- className="rounded-xl border border-zinc-200 bg-paper px-4 py-3 text-[14px] font-medium text-zinc-700 transition-colors hover:border-zinc-300 hover:bg-white hover:text-zinc-900"
270
- >
271
- {s.navLabel} →
272
- </Link>
273
- ))}
274
- </div>
275
- </section>
276
- </>
277
- )}
278
178
  </div>
279
179
  );
280
180
  }
281
181
 
282
- // A comparison page: hero + a feature-by-feature table + links to the other
283
- // comparisons.
182
+ // A comparison page: heading, a row-by-row table, and links to the others.
284
183
  export function ComparePage({
285
184
  cmp,
286
185
  all,
@@ -293,78 +192,42 @@ export function ComparePage({
293
192
  const others = all.filter((c) => c.slug !== cmp.slug);
294
193
  return (
295
194
  <div className="bg-white text-zinc-900">
296
- <section className={`${WRAP} pt-16 pb-16 sm:pt-20`}>
297
- <Link
298
- href="/"
299
- className="text-[13px] text-zinc-500 transition-colors hover:text-zinc-900"
300
- >
301
- ← Home
302
- </Link>
303
- <div className="mt-6">
304
- <Eyebrow>Compare</Eyebrow>
305
- </div>
306
- <h1 className="mt-4 max-w-2xl text-balance text-[2.25rem] font-semibold leading-[1.05] tracking-[-0.02em] sm:text-[3rem]">
307
- {cmp.title}
308
- </h1>
309
- <p className="mt-6 max-w-xl text-[17px] leading-relaxed text-zinc-500">
310
- {cmp.summary}
311
- </p>
312
- <div className="mt-8">
313
- <PrimaryButton href={ctaHref}>Get started</PrimaryButton>
314
- </div>
315
- </section>
316
-
317
- <Divider />
318
- <section className={`${WRAP} py-16`}>
319
- <div className="overflow-hidden rounded-2xl border border-zinc-200">
320
- <table className="w-full text-[14px]">
195
+ <PageHero title={cmp.title} summary={cmp.summary} ctaHref={ctaHref} />
196
+ <section className={`${WRAP} pb-20`}>
197
+ <div className="overflow-x-auto rounded-2xl ring-1 ring-zinc-200">
198
+ <table className="w-full min-w-[520px] text-[14px]">
321
199
  <thead>
322
- <tr className="border-b border-zinc-200 bg-paper text-left">
323
- <th className="px-5 py-3 font-medium text-zinc-400"></th>
324
- <th className="px-5 py-3 font-semibold text-zinc-900">Acme</th>
325
- <th className="px-5 py-3 font-medium text-zinc-500">
326
- {cmp.competitor}
327
- </th>
200
+ <tr className="border-b border-zinc-200 bg-zinc-50 text-left">
201
+ <th className="px-5 py-3 font-medium text-zinc-500" />
202
+ <th className="px-5 py-3 font-semibold text-zinc-900">{siteConfig.brand.name}</th>
203
+ <th className="px-5 py-3 font-medium text-zinc-500">{cmp.competitor}</th>
328
204
  </tr>
329
205
  </thead>
330
206
  <tbody>
331
207
  {cmp.rows.map((r) => (
332
- <tr
333
- key={r.dim}
334
- className="border-b border-zinc-100 last:border-0"
335
- >
208
+ <tr key={r.dim} className="border-b border-zinc-100 last:border-0">
336
209
  <td className="px-5 py-3.5 text-zinc-600">{r.dim}</td>
337
- <td className="px-5 py-3.5 font-medium text-zinc-900">
338
- <span className="mr-2 text-brand">✓</span>
339
- {r.acme}
340
- </td>
210
+ <td className="px-5 py-3.5 font-medium text-zinc-900">{r.acme}</td>
341
211
  <td className="px-5 py-3.5 text-zinc-500">{r.them}</td>
342
212
  </tr>
343
213
  ))}
344
214
  </tbody>
345
215
  </table>
346
216
  </div>
217
+ {others.length > 0 ? (
218
+ <div className="mt-10 flex flex-wrap gap-2">
219
+ {others.map((c) => (
220
+ <Link
221
+ key={c.slug}
222
+ href={`/compare/${c.slug}`}
223
+ className="rounded-full px-3.5 py-1.5 text-[13px] font-medium text-zinc-600 ring-1 ring-zinc-200 transition-colors hover:bg-zinc-50 hover:text-zinc-950"
224
+ >
225
+ {c.navLabel}
226
+ </Link>
227
+ ))}
228
+ </div>
229
+ ) : null}
347
230
  </section>
348
-
349
- {others.length > 0 && (
350
- <>
351
- <Divider />
352
- <section className={`${WRAP} py-16`}>
353
- <Eyebrow>More comparisons</Eyebrow>
354
- <div className="mt-6 grid gap-3 sm:grid-cols-3">
355
- {others.map((c) => (
356
- <Link
357
- key={c.slug}
358
- href={`/compare/${c.slug}`}
359
- className="rounded-xl border border-zinc-200 bg-paper px-4 py-3 text-[14px] font-medium text-zinc-700 transition-colors hover:border-zinc-300 hover:bg-white hover:text-zinc-900"
360
- >
361
- {c.navLabel} →
362
- </Link>
363
- ))}
364
- </div>
365
- </section>
366
- </>
367
- )}
368
231
  </div>
369
232
  );
370
233
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import React, { useState } from "react";
4
+ import { Check } from "lucide-react";
4
5
  import { PLANS, TRIAL_DAYS, annualSavingsPercent, formatPrice } from "@/lib/plans";
5
6
 
6
7
  /**
@@ -21,10 +22,10 @@ export function PricingTable({ signedIn }: { signedIn: boolean }) {
21
22
  aria-checked={annual}
22
23
  aria-label="Bill annually"
23
24
  onClick={() => setAnnual((v) => !v)}
24
- className={`relative h-6 w-11 rounded-full transition-colors ${annual ? "bg-zinc-900" : "bg-zinc-300"}`}
25
+ className={`relative h-6 w-11 shrink-0 rounded-full transition-colors ${annual ? "bg-zinc-900" : "bg-zinc-300"}`}
25
26
  >
26
27
  <span
27
- className={`absolute top-0.5 size-5 rounded-full bg-white transition-transform ${annual ? "translate-x-5" : "translate-x-0.5"}`}
28
+ className={`absolute left-0 top-0.5 size-5 rounded-full bg-white shadow-sm transition-transform duration-200 ${annual ? "translate-x-5" : "translate-x-0.5"}`}
28
29
  />
29
30
  </button>
30
31
  <span className={annual ? "font-medium text-zinc-900" : "text-zinc-500"}>
@@ -44,31 +45,31 @@ export function PricingTable({ signedIn }: { signedIn: boolean }) {
44
45
  return (
45
46
  <div
46
47
  key={p.id}
47
- className={`flex flex-col rounded-2xl border p-7 ${
48
+ className={`flex flex-col rounded-[20px] p-7 ${
48
49
  featured
49
- ? "border-zinc-900 bg-white shadow-[0_24px_60px_-30px_rgba(0,0,0,0.3)]"
50
- : "border-zinc-200 bg-paper"
50
+ ? "bg-white shadow-[0_0_0_1.5px_rgba(9,9,11,0.9),0_24px_60px_-30px_rgba(0,0,0,0.3)]"
51
+ : "bg-zinc-50/80 shadow-[0_0_0_1px_rgba(0,0,0,0.07)]"
51
52
  }`}
52
53
  >
53
54
  <div className="flex items-center justify-between">
54
55
  <h3 className="text-base font-semibold">{p.name}</h3>
55
56
  {featured && (
56
- <span className="font-mono text-[10px] uppercase tracking-[0.12em] text-brand">
57
+ <span className="rounded-full bg-brand-soft px-2.5 py-0.5 text-[12px] font-medium text-brand">
57
58
  {TRIAL_DAYS}-day free trial
58
59
  </span>
59
60
  )}
60
61
  </div>
61
62
  <p className="mt-1 text-[13px] text-zinc-500">{p.tagline}</p>
62
63
  <div className="mt-5 flex items-baseline gap-1">
63
- <span className="text-4xl font-semibold tracking-tight">{formatPrice(perMonth)}</span>
64
+ <span className="text-[2.6rem] font-semibold tracking-[-0.03em] tabular-nums">{formatPrice(perMonth)}</span>
64
65
  <span className="text-[13px] text-zinc-500">
65
66
  {p.monthly === 0 ? "forever" : `/ month${annual ? ", billed yearly" : ""}`}
66
67
  </span>
67
68
  </div>
68
69
  <ul className="mt-6 flex-1 space-y-3 text-[14px] text-zinc-600">
69
70
  {p.features.map((f) => (
70
- <li key={f} className="flex gap-2.5">
71
- <span className="mt-[3px] text-brand">✓</span>
71
+ <li key={f} className="flex items-center gap-2.5">
72
+ <Check className="size-4 shrink-0 text-brand" strokeWidth={2} />
72
73
  {f}
73
74
  </li>
74
75
  ))}
@@ -78,8 +79,8 @@ export function PricingTable({ signedIn }: { signedIn: boolean }) {
78
79
  href={href}
79
80
  className={
80
81
  featured
81
- ? "inline-flex h-10 w-full items-center justify-center rounded-lg bg-zinc-900 text-sm font-medium text-white transition-colors hover:bg-zinc-700"
82
- : "inline-flex h-10 w-full items-center justify-center rounded-lg border border-zinc-300 bg-white text-sm font-medium text-zinc-900 transition-colors hover:bg-zinc-50"
82
+ ? "inline-flex h-10 w-full items-center justify-center rounded-full bg-zinc-950 text-sm font-medium text-white transition-colors hover:bg-zinc-800"
83
+ : "inline-flex h-10 w-full items-center justify-center rounded-full bg-white text-sm font-medium text-zinc-900 ring-1 ring-zinc-200 transition-colors hover:bg-zinc-50"
83
84
  }
84
85
  >
85
86
  {signedIn && featured ? "Upgrade to Pro" : p.cta}