@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,117 +1,135 @@
1
1
  import React from "react";
2
2
  import { Link, type PageAuth } from "@pylonsync/react";
3
3
  import { siteConfig } from "@/lib/site.config";
4
+ import { CartButton } from "@/components/cart-button";
5
+ import { WRAP } from "@/components/marketing";
4
6
 
5
7
  // `(marketing)` is a ROUTE GROUP: the parens segment is stripped from every
6
8
  // URL (so `(marketing)/page.tsx` still serves `/`), and this layout wraps only
7
- // the pages inside the group — a slim nav up top and a footer below, both
8
- // driven by lib/site.config.ts. /login and /dashboard sit outside the group
9
- // and render bare in the root shell. `auth.user_id` is resolved server-side
10
- // from the session cookie before any HTML is sent, so the nav shows
11
- // "Dashboard" once the owner is signed in and "Sign in" otherwise — no flash,
12
- // no client fetch.
9
+ // the pages inside the group: an announcement bar, a sticky nav, and a footer,
10
+ // all driven by lib/site.config.ts. /login and /dashboard sit outside the
11
+ // group and render bare in the root shell. `auth.user_id` is resolved
12
+ // server-side from the session cookie before any HTML is sent, so the nav
13
+ // shows "Dashboard" once the owner is signed in and "Sign in" otherwise.
13
14
  interface LayoutProps {
14
15
  children: React.ReactNode;
15
16
  auth: PageAuth;
16
17
  }
17
18
 
19
+ const NAV_LINKS = [
20
+ { label: "Shop", href: "/#shop" },
21
+ { label: "Studio", href: "/#studio" },
22
+ { label: "Shipping", href: "/#shipping" },
23
+ ];
24
+
25
+ const NAV_LINK =
26
+ "relative text-[14px] text-ink/80 transition-colors duration-300 hover:text-ink after:absolute after:inset-x-0 after:-bottom-1 after:h-px after:origin-left after:scale-x-0 after:bg-ink after:transition-transform after:duration-500 after:ease-out-quint hover:after:scale-x-100";
27
+
18
28
  export default function MarketingLayout({ children, auth }: LayoutProps) {
19
29
  // A guest session (minted by <EnsureGuest> for the live stock grid) has a
20
- // `guest_…` user id — that's an anonymous visitor, NOT the signed-in owner,
21
- // so it shouldn't flip the nav to "Dashboard".
30
+ // `guest_…` user id. That is an anonymous visitor, not the signed-in owner,
31
+ // so it does not flip the nav to "Dashboard".
22
32
  const signedIn = Boolean(auth?.user_id && !auth.user_id.startsWith("guest_"));
23
33
  const { brand } = siteConfig;
24
34
 
25
35
  return (
26
- <>
27
- <header className="sticky top-0 z-30 bg-white/80 backdrop-blur">
28
- <div className="mx-auto flex h-14 max-w-3xl items-center justify-between px-6">
29
- <Link href="/" className="flex items-center gap-2">
30
- <span className="flex size-6 items-center justify-center rounded-[7px] bg-zinc-900 text-[13px] font-bold text-white">
31
- {brand.letter}
32
- </span>
33
- <span className="text-[15px] font-semibold tracking-tight text-zinc-900">
34
- {brand.name}
35
- </span>
36
+ <div className="grain flex min-h-screen flex-col bg-warm-white text-ink">
37
+ <div className="bg-espresso text-warm-white/85">
38
+ <p className={`${WRAP} flex min-h-9 items-center justify-center py-2 text-center text-[12px] leading-snug tracking-[0.01em] sm:text-[12.5px]`}>
39
+ {brand.announcement}
40
+ </p>
41
+ </div>
42
+
43
+ <header className="sticky top-0 z-30 border-b border-ink/10 bg-warm-white/85 backdrop-blur-md">
44
+ <div className={`${WRAP} grid h-16 grid-cols-[1fr_auto_1fr] items-center`}>
45
+ <nav className="hidden items-center gap-8 md:flex" aria-label="Sections">
46
+ {NAV_LINKS.map((l) => (
47
+ <a key={l.href} href={l.href} className={NAV_LINK}>
48
+ {l.label}
49
+ </a>
50
+ ))}
51
+ </nav>
52
+ <Link
53
+ href="/"
54
+ className="font-display col-start-1 justify-self-start text-[25px] leading-none tracking-[-0.015em] text-ink md:col-start-2 md:justify-self-center"
55
+ >
56
+ {brand.name}
36
57
  </Link>
37
- <nav className="flex items-center gap-2">
58
+ <div className="col-start-3 flex items-center justify-end gap-1 sm:gap-3">
38
59
  {signedIn ? (
39
- <Link
40
- href="/dashboard"
41
- className="inline-flex items-center rounded-full bg-zinc-900 px-3.5 py-1.5 text-[13px] font-medium text-white transition-colors hover:bg-zinc-700"
42
- >
60
+ <Link href="/dashboard" className={`${NAV_LINK} hidden sm:inline`}>
43
61
  Dashboard
44
62
  </Link>
45
63
  ) : (
46
- <Link
47
- href="/login"
48
- className="rounded-full px-3 py-1.5 text-[13px] font-medium text-zinc-600 transition-colors hover:text-zinc-900"
49
- >
64
+ <Link href="/login" className={`${NAV_LINK} hidden sm:inline`}>
50
65
  Sign in
51
66
  </Link>
52
67
  )}
53
- </nav>
68
+ {/* A client island: it reads the shared cart store so its count
69
+ matches the grid. */}
70
+ <CartButton />
71
+ </div>
54
72
  </div>
55
73
  </header>
56
74
 
57
75
  <main className="flex-1">{children}</main>
58
76
 
59
77
  <SiteFooter />
60
- </>
78
+ </div>
61
79
  );
62
80
  }
63
81
 
64
82
  function SiteFooter() {
65
83
  const { brand } = siteConfig;
66
84
  return (
67
- <footer className="border-t border-zinc-200/70 bg-white">
68
- <div className="mx-auto max-w-3xl px-6 py-12">
69
- <div className="flex flex-col items-start justify-between gap-6 sm:flex-row">
70
- <div className="max-w-sm">
71
- <Link href="/" className="inline-flex items-center gap-2">
72
- <span className="flex size-6 items-center justify-center rounded-[7px] bg-zinc-900 text-[13px] font-bold text-white">
73
- {brand.letter}
74
- </span>
75
- <span className="text-[15px] font-semibold tracking-tight text-zinc-900">
76
- {brand.name}
77
- </span>
85
+ <footer className="bg-espresso text-warm-white">
86
+ <div className={`${WRAP} pt-20 pb-10`}>
87
+ <div className="grid gap-12 md:grid-cols-[1.4fr_1fr_1fr_1fr]">
88
+ <div className="max-w-xs">
89
+ <Link href="/" className="font-display text-[32px] leading-none tracking-[-0.015em]">
90
+ {brand.name}
78
91
  </Link>
79
- <p className="mt-3 text-[13px] leading-relaxed text-zinc-500">
80
- {brand.footerBlurb}
81
- </p>
92
+ <p className="mt-4 text-[14px] leading-relaxed text-warm-white/60">{brand.footerBlurb}</p>
82
93
  </div>
83
- <div className="flex items-center gap-4">
84
- {brand.socials.map((s) => (
85
- <a
86
- key={s.label}
87
- href={s.href}
88
- aria-label={s.label}
89
- className="text-zinc-400 transition-colors hover:text-zinc-900"
90
- >
91
- <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
92
- <path d={s.path} />
93
- </svg>
94
+ <FooterColumn title="Shop">
95
+ {NAV_LINKS.map((l) => (
96
+ <li key={l.href}>
97
+ <a href={l.href} className="transition-colors hover:text-warm-white">
98
+ {l.label}
99
+ </a>
100
+ </li>
101
+ ))}
102
+ </FooterColumn>
103
+ <FooterColumn title="Studio">
104
+ {brand.address.map((line) => (
105
+ <li key={line}>{line}</li>
106
+ ))}
107
+ </FooterColumn>
108
+ <FooterColumn title="Contact">
109
+ <li>
110
+ <a href={`mailto:${brand.email}`} className="transition-colors hover:text-warm-white">
111
+ {brand.email}
94
112
  </a>
113
+ </li>
114
+ {brand.socials.map((s) => (
115
+ <li key={s.label}>
116
+ <a href={s.href} className="inline-flex items-center gap-2 transition-colors hover:text-warm-white">
117
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
118
+ <path d={s.path} />
119
+ </svg>
120
+ {s.label}
121
+ </a>
122
+ </li>
95
123
  ))}
96
- <a
97
- href={`mailto:${brand.email}`}
98
- aria-label="Email"
99
- className="text-zinc-400 transition-colors hover:text-zinc-900"
100
- >
101
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
102
- <rect x="3" y="5" width="18" height="14" rx="2" />
103
- <path d="m3 7 9 6 9-6" />
104
- </svg>
105
- </a>
106
- </div>
124
+ </FooterColumn>
107
125
  </div>
108
- <div className="mt-10 flex flex-col items-start justify-between gap-3 border-t border-zinc-200/70 pt-6 text-[12px] text-zinc-400 sm:flex-row sm:items-center">
126
+ <div className="mt-20 flex flex-col items-start justify-between gap-3 border-t border-warm-white/10 pt-6 text-[12.5px] text-warm-white/50 sm:flex-row sm:items-center">
109
127
  <span>
110
128
  © {new Date().getFullYear()} {brand.copyrightName}
111
129
  </span>
112
130
  <span>
113
131
  Built with{" "}
114
- <a href="https://pylonsync.com" className="font-medium text-zinc-600 hover:text-zinc-900">
132
+ <a href="https://pylonsync.com" className="text-warm-white/80 transition-colors hover:text-warm-white">
115
133
  Pylon
116
134
  </a>
117
135
  </span>
@@ -120,3 +138,12 @@ function SiteFooter() {
120
138
  </footer>
121
139
  );
122
140
  }
141
+
142
+ function FooterColumn({ title, children }: { title: string; children: React.ReactNode }) {
143
+ return (
144
+ <div>
145
+ <h3 className="text-[13px] font-medium text-warm-white">{title}</h3>
146
+ <ul className="mt-4 space-y-2.5 text-[14px] text-warm-white/60">{children}</ul>
147
+ </div>
148
+ );
149
+ }
@@ -1,23 +1,24 @@
1
1
  import React from "react";
2
2
  import { Link, type NotFoundProps } from "@pylonsync/react";
3
+ import { WRAP, BUTTON_DARK } from "@/components/marketing";
3
4
 
4
5
  // `(marketing)/not-found.tsx` → rendered at HTTP 404 for any unmatched URL
5
6
  // (and when a page calls `response.notFound()`). It lives inside the
6
7
  // `(marketing)` group on purpose: a group segment adds no URL prefix, so this
7
- // is still the root 404 boundary, but it wraps in the marketing layout — a
8
- // missing URL gets the site nav + footer instead of a bare page. Hydrated, so
9
- // the link is a client nav.
8
+ // is still the root 404 boundary, but it wraps in the marketing layout, so a
9
+ // missing URL gets the site nav + footer. Hydrated, so the link is a client nav.
10
10
  export default function NotFound(_props: NotFoundProps) {
11
11
  return (
12
- <div className="mx-auto flex min-h-[60vh] max-w-3xl flex-col items-center justify-center px-6 text-center">
13
- <h1 className="text-3xl font-semibold tracking-tight">404</h1>
14
- <p className="mt-2 text-zinc-500">We couldn&apos;t find that page.</p>
15
- <Link
16
- href="/"
17
- className="mt-6 inline-flex h-10 items-center rounded-full bg-zinc-900 px-5 text-sm font-medium text-white transition-colors hover:bg-zinc-700"
18
- >
19
- Back home
12
+ <section className={`${WRAP} flex min-h-[64vh] flex-col items-start justify-center py-24`}>
13
+ <h1 className="font-display text-[3rem] font-light leading-none tracking-[-0.03em] text-ink sm:text-[4.25rem]">
14
+ Page not found.
15
+ </h1>
16
+ <p className="mt-5 max-w-[40ch] text-[17px] leading-relaxed text-ink-2">
17
+ The link may be old, or the product may be gone for good.
18
+ </p>
19
+ <Link href="/#shop" className={`${BUTTON_DARK} mt-9`}>
20
+ Back to the shop
20
21
  </Link>
21
- </div>
22
+ </section>
22
23
  );
23
24
  }
@@ -1,95 +1,156 @@
1
1
  import React from "react";
2
2
  import { type Metadata } from "@pylonsync/react";
3
- import { WRAP, Eyebrow, Divider, SectionHead, FeatureGrid, initials } from "@/components/marketing";
3
+ import { ArrowRight } from "lucide-react";
4
+ import { WRAP, BUTTON_DARK, BUTTON_LINE, SectionHeading } from "@/components/marketing";
5
+ import { ShelfCount } from "@/components/shelf-count";
4
6
  import { ShopGrid } from "./shop-client";
5
7
  import { siteConfig } from "@/lib/site.config";
6
8
 
7
9
  export const metadata: Metadata = {
8
10
  title: siteConfig.seo.title,
9
11
  description: siteConfig.seo.description,
10
- openGraph: { title: siteConfig.seo.title, description: siteConfig.seo.description, type: "website" },
12
+ openGraph: {
13
+ title: siteConfig.seo.title,
14
+ description: siteConfig.seo.description,
15
+ type: "website",
16
+ images: [{ url: siteConfig.hero.image, alt: siteConfig.hero.imageAlt }],
17
+ },
11
18
  };
12
19
 
13
- // `app/(marketing)/page.tsx` → `/` (the group segment adds no URL prefix). Server-rendered storefront. Hero, value props, reviews,
14
- // and policies are static server HTML (SEO + first paint); the product grid
15
- // (#shop) is a client island with live stock. All copy comes from siteConfig;
16
- // the product list seeds the DB on first visit. Doesn't read `auth`, so the
17
- // public page stays cacheable.
20
+ // `app/(marketing)/page.tsx` → `/` (the group segment adds no URL prefix).
21
+ // Server-rendered storefront: a full-bleed hero, the live product grid, the
22
+ // studio story, reviews, and shipping terms. Everything except the grid (#shop)
23
+ // and the hero's shelf count is static server HTML (SEO + first paint). All
24
+ // copy comes from siteConfig; the product list seeds the DB on first visit.
25
+ // Doesn't read `auth`, so the public page stays cacheable.
18
26
  export default function LandingPage() {
19
- const { hero, products, valueProps, reviews, policies } = siteConfig;
27
+ const { hero, products, studio, reviews, policies } = siteConfig;
20
28
 
21
29
  return (
22
- <div className="bg-white text-zinc-900">
23
- {/* HERO */}
24
- <section className={`${WRAP} pt-16 pb-12 sm:pt-20`}>
25
- <p className="font-mono text-[11px] uppercase tracking-[0.16em] text-brand">{hero.tagline}</p>
26
- <h1 className="mt-4 max-w-3xl text-balance text-[2.5rem] font-semibold leading-[1.04] tracking-[-0.02em] sm:text-[3.25rem]">
27
- {hero.headline}
28
- </h1>
29
- <p className="mt-5 max-w-xl text-[17px] leading-relaxed text-zinc-500">{hero.subcopy}</p>
30
- <div className="mt-7">
31
- <a href="#shop" className="inline-flex items-center rounded-full bg-brand px-5 py-2.5 text-sm font-medium text-white transition-opacity hover:opacity-90">
32
- {hero.ctaLabel}
33
- </a>
30
+ <>
31
+ {/* HERO. Desktop: the photo fills the first screen and the copy sits on
32
+ its open left side. Mobile: the photo stacks above the copy. */}
33
+ <section className="relative overflow-hidden bg-stone md:h-[calc(100svh-100px)] md:min-h-[600px] md:max-h-[940px]">
34
+ <div className="relative aspect-[4/5] overflow-hidden sm:aspect-[16/10] md:absolute md:inset-0 md:aspect-auto">
35
+ {/* eslint-disable-next-line @next/next/no-img-element */}
36
+ <img
37
+ src={hero.image}
38
+ alt={hero.imageAlt}
39
+ fetchPriority="high"
40
+ className="settle size-full object-cover object-[78%_50%] md:object-[center_60%]"
41
+ />
42
+ {/* Softens the left edge so the headline reads on any crop. */}
43
+ <div className="absolute inset-0 hidden bg-gradient-to-r from-[#efe5d6]/70 via-[#efe5d6]/10 to-transparent md:block" />
44
+ </div>
45
+
46
+ <div className={`${WRAP} relative flex h-full flex-col justify-center py-12 md:py-0`}>
47
+ <div className="max-w-[560px]">
48
+ <h1 className="rise font-display text-[3.25rem] font-light leading-[0.98] tracking-[-0.03em] text-ink sm:text-[4.5rem] lg:text-[5rem] xl:text-[6rem]">
49
+ {hero.headline}
50
+ </h1>
51
+ <p
52
+ className="rise mt-7 max-w-[34ch] text-[17px] leading-[1.6] text-ink/75 sm:text-[18px]"
53
+ style={{ animationDelay: "120ms" }}
54
+ >
55
+ {hero.subcopy}
56
+ </p>
57
+ <div className="rise mt-9 flex flex-wrap items-center gap-3" style={{ animationDelay: "220ms" }}>
58
+ <a href="#shop" className={`${BUTTON_DARK} group`}>
59
+ {hero.ctaLabel}
60
+ <ArrowRight
61
+ className="size-4 transition-transform duration-500 ease-out-quint group-hover:translate-x-1"
62
+ strokeWidth={1.5}
63
+ />
64
+ </a>
65
+ <a href="#studio" className={BUTTON_LINE}>
66
+ {hero.secondaryLabel}
67
+ </a>
68
+ </div>
69
+ <div className="rise mt-10" style={{ animationDelay: "320ms" }}>
70
+ <ShelfCount />
71
+ </div>
72
+ </div>
34
73
  </div>
35
74
  </section>
36
75
 
37
76
  {/* PRODUCTS */}
38
- <Divider />
39
- <section id="shop" className={`${WRAP} py-14`}>
40
- <SectionHead eyebrow={products.eyebrow} title={products.headline} />
41
- <div className="mt-8">
42
- <ShopGrid />
77
+ <section id="shop" className="scroll-mt-16 py-24 sm:py-32">
78
+ <div className={WRAP}>
79
+ <div className="flex flex-col justify-between gap-5 md:flex-row md:items-end">
80
+ <SectionHeading>{products.headline}</SectionHeading>
81
+ <p className="max-w-[40ch] text-[15.5px] leading-relaxed text-ink-2">{products.subcopy}</p>
82
+ </div>
83
+ <div className="mt-14 sm:mt-16">
84
+ <ShopGrid />
85
+ </div>
43
86
  </div>
44
87
  </section>
45
88
 
46
- {/* VALUE PROPS */}
47
- <Divider />
48
- <section className={`${WRAP} py-14`}>
49
- <SectionHead eyebrow={valueProps.eyebrow} title={valueProps.headline} />
50
- <div className="mt-10">
51
- <FeatureGrid items={valueProps.items} />
89
+ {/* STUDIO: type only. Headline on the left, story and figures on the right. */}
90
+ <section id="studio" className="scroll-mt-16 bg-espresso text-warm-white">
91
+ <div className={`${WRAP} grid gap-12 py-24 sm:py-32 md:grid-cols-[1.1fr_1fr] md:gap-20`}>
92
+ <h2 className="font-display max-w-[14ch] text-[2.75rem] font-light leading-[1] tracking-[-0.03em] text-balance sm:text-[4rem] lg:text-[4.75rem]">
93
+ {studio.headline}
94
+ </h2>
95
+ <div className="md:pt-3">
96
+ <div className="max-w-[46ch] space-y-4 text-[16px] leading-[1.7] text-warm-white/70">
97
+ {studio.body.map((p) => (
98
+ <p key={p}>{p}</p>
99
+ ))}
100
+ </div>
101
+ <dl className="mt-12 grid grid-cols-3 gap-6 border-t border-warm-white/15 pt-8">
102
+ {studio.facts.map((f) => (
103
+ <div key={f.label}>
104
+ <dt className="sr-only">{f.label}</dt>
105
+ <dd>
106
+ <span className="font-display block text-[2rem] font-light leading-none tracking-[-0.02em] sm:text-[2.5rem]">
107
+ {f.value}
108
+ </span>
109
+ <span className="mt-2 block text-[13px] leading-snug text-warm-white/55">{f.label}</span>
110
+ </dd>
111
+ </div>
112
+ ))}
113
+ </dl>
114
+ </div>
52
115
  </div>
53
116
  </section>
54
117
 
55
118
  {/* REVIEWS */}
56
119
  {reviews && reviews.items.length > 0 ? (
57
- <>
58
- <Divider />
59
- <section className={`${WRAP} py-14`}>
60
- <SectionHead eyebrow={reviews.eyebrow} title={reviews.headline} />
61
- <div className="mt-8 grid gap-5 sm:grid-cols-3">
120
+ <section className="py-24 sm:py-32">
121
+ <div className={WRAP}>
122
+ <SectionHeading>{reviews.headline}</SectionHeading>
123
+ <div className="mt-14 grid gap-12 md:grid-cols-3 md:gap-10">
62
124
  {reviews.items.map((r) => (
63
- <figure key={r.name} className="flex flex-col rounded-2xl border border-zinc-200 bg-paper p-6">
64
- {r.rating ? (
65
- <div className="text-[13px] tracking-wide text-brand">
66
- {"★".repeat(r.rating)}
67
- <span className="text-zinc-200">{"★".repeat(5 - r.rating)}</span>
68
- </div>
69
- ) : null}
70
- <blockquote className="mt-3 text-[14px] leading-relaxed text-zinc-600">&ldquo;{r.quote}&rdquo;</blockquote>
71
- <figcaption className="mt-4 flex items-center gap-3">
72
- <span className="flex size-8 items-center justify-center rounded-full bg-zinc-200 text-[11px] font-semibold text-zinc-500">
73
- {initials(r.name)}
74
- </span>
75
- <div className="text-[13px] font-semibold">{r.name}</div>
125
+ <figure key={r.name} className="flex flex-col border-t border-ink/15 pt-7">
126
+ <blockquote className="font-display text-[1.5rem] font-light leading-[1.3] tracking-[-0.01em] text-ink">
127
+ &ldquo;{r.quote}&rdquo;
128
+ </blockquote>
129
+ <figcaption className="mt-6 text-[13.5px] text-ink-2">
130
+ {r.name}
131
+ {r.product ? <span className="text-ink-2/70">, on {r.product}</span> : null}
76
132
  </figcaption>
77
133
  </figure>
78
134
  ))}
79
135
  </div>
80
- </section>
81
- </>
136
+ </div>
137
+ </section>
82
138
  ) : null}
83
139
 
84
- {/* POLICIES */}
85
- <Divider />
86
- <section className={`${WRAP} py-14`}>
87
- <Eyebrow>{policies.eyebrow}</Eyebrow>
88
- <h2 className="mt-4 text-balance text-2xl font-semibold leading-[1.15] tracking-[-0.02em] sm:text-3xl">{policies.headline}</h2>
89
- <div className="mt-8">
90
- <FeatureGrid items={policies.items.map((p) => ({ title: p.title, body: p.body }))} />
140
+ {/* SHIPPING AND RETURNS */}
141
+ <section id="shipping" className="scroll-mt-16 border-t border-ink/10 bg-stone/50 py-24 sm:py-28">
142
+ <div className={`${WRAP} grid gap-12 md:grid-cols-[1fr_1.6fr]`}>
143
+ <SectionHeading>{policies.headline}</SectionHeading>
144
+ <dl className="grid gap-x-12 gap-y-10 sm:grid-cols-2">
145
+ {policies.items.map((p) => (
146
+ <div key={p.title}>
147
+ <dt className="font-display text-[1.375rem] text-ink">{p.title}</dt>
148
+ <dd className="mt-2 text-[15px] leading-relaxed text-ink-2">{p.body}</dd>
149
+ </div>
150
+ ))}
151
+ </dl>
91
152
  </div>
92
153
  </section>
93
- </div>
154
+ </>
94
155
  );
95
156
  }