@pylonsync/create-pylon 0.3.274 → 0.3.276

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 (340) hide show
  1. package/bin/create-pylon.js +80 -0
  2. package/package.json +1 -1
  3. package/templates/ARCHETYPES.md +339 -0
  4. package/templates/agency/.env.example +12 -0
  5. package/templates/agency/AGENTS.md +61 -0
  6. package/templates/agency/README.md +90 -0
  7. package/templates/agency/app/auth-form.tsx +129 -0
  8. package/templates/agency/app/contact-form.tsx +258 -0
  9. package/templates/agency/app/dashboard/dashboard-client.tsx +1440 -0
  10. package/templates/agency/app/dashboard/page.tsx +70 -0
  11. package/templates/agency/app/error.tsx +26 -0
  12. package/templates/agency/app/globals.css +148 -0
  13. package/templates/agency/app/layout.tsx +174 -0
  14. package/templates/agency/app/login/page.tsx +39 -0
  15. package/templates/agency/app/not-found.tsx +19 -0
  16. package/templates/agency/app/page.tsx +249 -0
  17. package/templates/agency/app/robots.ts +12 -0
  18. package/templates/agency/app/seeder.tsx +26 -0
  19. package/templates/agency/app/sitemap.ts +9 -0
  20. package/templates/agency/app/work/[slug]/page.tsx +182 -0
  21. package/templates/agency/app/work/page.tsx +83 -0
  22. package/templates/agency/app.ts +284 -0
  23. package/templates/agency/components/marketing.tsx +187 -0
  24. package/templates/agency/components/section-scroller.tsx +35 -0
  25. package/templates/agency/components/ui/button.tsx +56 -0
  26. package/templates/agency/components/ui/card.tsx +90 -0
  27. package/templates/agency/components.json +20 -0
  28. package/templates/agency/functions/bookInquiry.ts +42 -0
  29. package/templates/agency/functions/clientsForOwner.ts +27 -0
  30. package/templates/agency/functions/declineInquiry.ts +41 -0
  31. package/templates/agency/functions/deleteClient.ts +27 -0
  32. package/templates/agency/functions/deleteInvoice.ts +19 -0
  33. package/templates/agency/functions/deleteProject.ts +20 -0
  34. package/templates/agency/functions/inquiriesForOwner.ts +31 -0
  35. package/templates/agency/functions/invoicesForOwner.ts +27 -0
  36. package/templates/agency/functions/seedCapacity.ts +26 -0
  37. package/templates/agency/functions/seedProjects.ts +41 -0
  38. package/templates/agency/functions/seedStudioBackoffice.ts +74 -0
  39. package/templates/agency/functions/setCapacity.ts +32 -0
  40. package/templates/agency/functions/setInvoiceStatus.ts +27 -0
  41. package/templates/agency/functions/setProjectFlags.ts +35 -0
  42. package/templates/agency/functions/submitInquiry.ts +55 -0
  43. package/templates/agency/functions/upsertClient.ts +73 -0
  44. package/templates/agency/functions/upsertInvoice.ts +113 -0
  45. package/templates/agency/functions/upsertProject.ts +97 -0
  46. package/templates/agency/gitignore +10 -0
  47. package/templates/agency/lib/agency.ts +189 -0
  48. package/templates/agency/lib/invoice-pdf.tsx +174 -0
  49. package/templates/agency/lib/owner.ts +26 -0
  50. package/templates/agency/lib/site.config.ts +418 -0
  51. package/templates/agency/lib/utils.ts +10 -0
  52. package/templates/agency/package.json +35 -0
  53. package/templates/agency/tsconfig.json +18 -0
  54. package/templates/ai-chat/.env.example +33 -0
  55. package/templates/ai-chat/AGENTS.md +61 -0
  56. package/templates/ai-chat/README.md +99 -0
  57. package/templates/ai-chat/app/auth-form.tsx +124 -0
  58. package/templates/ai-chat/app/chat-client.tsx +727 -0
  59. package/templates/ai-chat/app/error.tsx +26 -0
  60. package/templates/ai-chat/app/globals.css +148 -0
  61. package/templates/ai-chat/app/layout.tsx +75 -0
  62. package/templates/ai-chat/app/login/page.tsx +39 -0
  63. package/templates/ai-chat/app/not-found.tsx +19 -0
  64. package/templates/ai-chat/app/page.tsx +23 -0
  65. package/templates/ai-chat/app.ts +121 -0
  66. package/templates/ai-chat/components.json +20 -0
  67. package/templates/ai-chat/functions/deleteConversation.ts +33 -0
  68. package/templates/ai-chat/gitignore +10 -0
  69. package/templates/ai-chat/lib/site.config.ts +103 -0
  70. package/templates/ai-chat/lib/utils.ts +10 -0
  71. package/templates/ai-chat/package.json +34 -0
  72. package/templates/ai-chat/tsconfig.json +18 -0
  73. package/templates/ai-studio/.env.example +19 -0
  74. package/templates/ai-studio/AGENTS.md +61 -0
  75. package/templates/ai-studio/README.md +83 -0
  76. package/templates/ai-studio/app/auth-form.tsx +124 -0
  77. package/templates/ai-studio/app/error.tsx +26 -0
  78. package/templates/ai-studio/app/globals.css +148 -0
  79. package/templates/ai-studio/app/layout.tsx +75 -0
  80. package/templates/ai-studio/app/login/page.tsx +39 -0
  81. package/templates/ai-studio/app/not-found.tsx +19 -0
  82. package/templates/ai-studio/app/page.tsx +34 -0
  83. package/templates/ai-studio/app/studio-client.tsx +357 -0
  84. package/templates/ai-studio/app.ts +108 -0
  85. package/templates/ai-studio/components.json +20 -0
  86. package/templates/ai-studio/functions/_getGeneration.ts +25 -0
  87. package/templates/ai-studio/functions/_updateGeneration.ts +37 -0
  88. package/templates/ai-studio/functions/generate.ts +42 -0
  89. package/templates/ai-studio/functions/pollGeneration.ts +134 -0
  90. package/templates/ai-studio/gitignore +10 -0
  91. package/templates/ai-studio/lib/site.config.ts +80 -0
  92. package/templates/ai-studio/lib/studio.ts +52 -0
  93. package/templates/ai-studio/lib/utils.ts +10 -0
  94. package/templates/ai-studio/package.json +34 -0
  95. package/templates/ai-studio/tsconfig.json +18 -0
  96. package/templates/creator/.env.example +12 -0
  97. package/templates/creator/AGENTS.md +61 -0
  98. package/templates/creator/README.md +67 -0
  99. package/templates/creator/app/auth-form.tsx +129 -0
  100. package/templates/creator/app/dashboard/dashboard-client.tsx +297 -0
  101. package/templates/creator/app/dashboard/page.tsx +70 -0
  102. package/templates/creator/app/error.tsx +26 -0
  103. package/templates/creator/app/globals.css +148 -0
  104. package/templates/creator/app/layout.tsx +160 -0
  105. package/templates/creator/app/login/page.tsx +39 -0
  106. package/templates/creator/app/newsletter-signup.tsx +162 -0
  107. package/templates/creator/app/not-found.tsx +19 -0
  108. package/templates/creator/app/page.tsx +160 -0
  109. package/templates/creator/app/robots.ts +12 -0
  110. package/templates/creator/app/sitemap.ts +9 -0
  111. package/templates/creator/app.ts +134 -0
  112. package/templates/creator/components/marketing.tsx +148 -0
  113. package/templates/creator/components/section-scroller.tsx +35 -0
  114. package/templates/creator/components/ui/button.tsx +56 -0
  115. package/templates/creator/components/ui/card.tsx +90 -0
  116. package/templates/creator/components.json +20 -0
  117. package/templates/creator/functions/subscribe.ts +82 -0
  118. package/templates/creator/functions/subscriberStats.ts +75 -0
  119. package/templates/creator/gitignore +10 -0
  120. package/templates/creator/lib/owner.ts +26 -0
  121. package/templates/creator/lib/site.config.ts +173 -0
  122. package/templates/creator/lib/stats.ts +30 -0
  123. package/templates/creator/lib/utils.ts +10 -0
  124. package/templates/creator/package.json +34 -0
  125. package/templates/creator/tsconfig.json +18 -0
  126. package/templates/default/app/layout.tsx +26 -27
  127. package/templates/default/app/page.tsx +90 -274
  128. package/templates/default/lib/products.ts +9 -122
  129. package/templates/default/lib/site.config.ts +739 -0
  130. package/templates/default/lib/site.ts +14 -261
  131. package/templates/directory/.env.example +12 -0
  132. package/templates/directory/AGENTS.md +61 -0
  133. package/templates/directory/README.md +80 -0
  134. package/templates/directory/app/auth-form.tsx +129 -0
  135. package/templates/directory/app/dashboard/dashboard-client.tsx +205 -0
  136. package/templates/directory/app/dashboard/page.tsx +70 -0
  137. package/templates/directory/app/directory-browse.tsx +328 -0
  138. package/templates/directory/app/error.tsx +26 -0
  139. package/templates/directory/app/globals.css +148 -0
  140. package/templates/directory/app/layout.tsx +171 -0
  141. package/templates/directory/app/login/page.tsx +39 -0
  142. package/templates/directory/app/not-found.tsx +19 -0
  143. package/templates/directory/app/page.tsx +50 -0
  144. package/templates/directory/app/robots.ts +12 -0
  145. package/templates/directory/app/sitemap.ts +9 -0
  146. package/templates/directory/app/submit/page.tsx +30 -0
  147. package/templates/directory/app/submit-form.tsx +151 -0
  148. package/templates/directory/app.ts +146 -0
  149. package/templates/directory/components/marketing.tsx +148 -0
  150. package/templates/directory/components/section-scroller.tsx +35 -0
  151. package/templates/directory/components/ui/button.tsx +56 -0
  152. package/templates/directory/components/ui/card.tsx +90 -0
  153. package/templates/directory/components.json +20 -0
  154. package/templates/directory/functions/approveSubmission.ts +45 -0
  155. package/templates/directory/functions/rejectSubmission.ts +20 -0
  156. package/templates/directory/functions/seedListings.ts +33 -0
  157. package/templates/directory/functions/submissionsForOwner.ts +29 -0
  158. package/templates/directory/functions/submitListing.ts +63 -0
  159. package/templates/directory/functions/upvote.ts +24 -0
  160. package/templates/directory/gitignore +10 -0
  161. package/templates/directory/lib/directory.ts +45 -0
  162. package/templates/directory/lib/owner.ts +26 -0
  163. package/templates/directory/lib/site.config.ts +130 -0
  164. package/templates/directory/lib/utils.ts +10 -0
  165. package/templates/directory/package.json +34 -0
  166. package/templates/directory/tsconfig.json +18 -0
  167. package/templates/local-service/.env.example +12 -0
  168. package/templates/local-service/AGENTS.md +61 -0
  169. package/templates/local-service/README.md +82 -0
  170. package/templates/local-service/app/auth-form.tsx +129 -0
  171. package/templates/local-service/app/booking-widget.tsx +399 -0
  172. package/templates/local-service/app/dashboard/dashboard-client.tsx +304 -0
  173. package/templates/local-service/app/dashboard/page.tsx +63 -0
  174. package/templates/local-service/app/error.tsx +26 -0
  175. package/templates/local-service/app/globals.css +148 -0
  176. package/templates/local-service/app/layout.tsx +151 -0
  177. package/templates/local-service/app/login/page.tsx +39 -0
  178. package/templates/local-service/app/not-found.tsx +19 -0
  179. package/templates/local-service/app/page.tsx +233 -0
  180. package/templates/local-service/app/robots.ts +12 -0
  181. package/templates/local-service/app/sitemap.ts +9 -0
  182. package/templates/local-service/app.ts +131 -0
  183. package/templates/local-service/components/marketing.tsx +162 -0
  184. package/templates/local-service/components/section-scroller.tsx +35 -0
  185. package/templates/local-service/components/ui/button.tsx +56 -0
  186. package/templates/local-service/components/ui/card.tsx +90 -0
  187. package/templates/local-service/components.json +20 -0
  188. package/templates/local-service/functions/bookingsForOwner.ts +30 -0
  189. package/templates/local-service/functions/cancelBooking.ts +27 -0
  190. package/templates/local-service/functions/confirmBooking.ts +18 -0
  191. package/templates/local-service/functions/createBooking.ts +98 -0
  192. package/templates/local-service/gitignore +10 -0
  193. package/templates/local-service/lib/booking.ts +24 -0
  194. package/templates/local-service/lib/owner.ts +26 -0
  195. package/templates/local-service/lib/site.config.ts +232 -0
  196. package/templates/local-service/lib/slots.ts +97 -0
  197. package/templates/local-service/lib/utils.ts +10 -0
  198. package/templates/local-service/package.json +34 -0
  199. package/templates/local-service/tsconfig.json +18 -0
  200. package/templates/marketplace/.env.example +9 -0
  201. package/templates/marketplace/AGENTS.md +61 -0
  202. package/templates/marketplace/README.md +78 -0
  203. package/templates/marketplace/app/_components/CategoryIcon.tsx +40 -0
  204. package/templates/marketplace/app/error.tsx +26 -0
  205. package/templates/marketplace/app/globals.css +64 -0
  206. package/templates/marketplace/app/layout.tsx +60 -0
  207. package/templates/marketplace/app/listing/[id]/page.tsx +163 -0
  208. package/templates/marketplace/app/me/page.tsx +15 -0
  209. package/templates/marketplace/app/not-found.tsx +20 -0
  210. package/templates/marketplace/app/page.tsx +159 -0
  211. package/templates/marketplace/app/robots.ts +12 -0
  212. package/templates/marketplace/app/sell/page.tsx +26 -0
  213. package/templates/marketplace/app/sitemap.ts +14 -0
  214. package/templates/marketplace/app.ts +190 -0
  215. package/templates/marketplace/client/AuthNav.tsx +46 -0
  216. package/templates/marketplace/client/LiveTicker.tsx +104 -0
  217. package/templates/marketplace/client/LoginCard.tsx +130 -0
  218. package/templates/marketplace/client/MarketProvider.tsx +148 -0
  219. package/templates/marketplace/client/MyMarket.tsx +180 -0
  220. package/templates/marketplace/client/OfferPanel.tsx +355 -0
  221. package/templates/marketplace/client/SeedOnEmpty.tsx +26 -0
  222. package/templates/marketplace/client/SellForm.tsx +160 -0
  223. package/templates/marketplace/client/WatchButton.tsx +88 -0
  224. package/templates/marketplace/client/market.ts +341 -0
  225. package/templates/marketplace/functions/buyNow.ts +78 -0
  226. package/templates/marketplace/functions/makeOffer.ts +65 -0
  227. package/templates/marketplace/functions/respondToOffer.ts +62 -0
  228. package/templates/marketplace/functions/seedMarket.ts +90 -0
  229. package/templates/marketplace/gitignore +10 -0
  230. package/templates/marketplace/package.json +35 -0
  231. package/templates/marketplace/tsconfig.json +14 -0
  232. package/templates/marketplace/ui/badge.tsx +30 -0
  233. package/templates/marketplace/ui/button.tsx +49 -0
  234. package/templates/marketplace/ui/card.tsx +48 -0
  235. package/templates/marketplace/ui/input.tsx +17 -0
  236. package/templates/marketplace/ui/label.tsx +18 -0
  237. package/templates/marketplace/ui/textarea.tsx +17 -0
  238. package/templates/marketplace/ui/tokens.css +32 -0
  239. package/templates/marketplace/ui/utils.ts +6 -0
  240. package/templates/restaurant/.env.example +12 -0
  241. package/templates/restaurant/AGENTS.md +61 -0
  242. package/templates/restaurant/README.md +77 -0
  243. package/templates/restaurant/app/auth-form.tsx +129 -0
  244. package/templates/restaurant/app/dashboard/dashboard-client.tsx +263 -0
  245. package/templates/restaurant/app/dashboard/page.tsx +59 -0
  246. package/templates/restaurant/app/error.tsx +26 -0
  247. package/templates/restaurant/app/globals.css +148 -0
  248. package/templates/restaurant/app/layout.tsx +151 -0
  249. package/templates/restaurant/app/login/page.tsx +39 -0
  250. package/templates/restaurant/app/not-found.tsx +19 -0
  251. package/templates/restaurant/app/page.tsx +194 -0
  252. package/templates/restaurant/app/reservation-widget.tsx +359 -0
  253. package/templates/restaurant/app/robots.ts +12 -0
  254. package/templates/restaurant/app/sitemap.ts +9 -0
  255. package/templates/restaurant/app.ts +115 -0
  256. package/templates/restaurant/components/marketing.tsx +162 -0
  257. package/templates/restaurant/components/section-scroller.tsx +35 -0
  258. package/templates/restaurant/components/ui/button.tsx +56 -0
  259. package/templates/restaurant/components/ui/card.tsx +90 -0
  260. package/templates/restaurant/components.json +20 -0
  261. package/templates/restaurant/functions/cancelReservation.ts +26 -0
  262. package/templates/restaurant/functions/confirmReservation.ts +17 -0
  263. package/templates/restaurant/functions/createReservation.ts +92 -0
  264. package/templates/restaurant/functions/reservationsForOwner.ts +28 -0
  265. package/templates/restaurant/gitignore +10 -0
  266. package/templates/restaurant/lib/owner.ts +26 -0
  267. package/templates/restaurant/lib/reservation.ts +22 -0
  268. package/templates/restaurant/lib/site.config.ts +218 -0
  269. package/templates/restaurant/lib/slots.ts +55 -0
  270. package/templates/restaurant/lib/utils.ts +10 -0
  271. package/templates/restaurant/package.json +34 -0
  272. package/templates/restaurant/tsconfig.json +18 -0
  273. package/templates/shop/.env.example +32 -0
  274. package/templates/shop/AGENTS.md +61 -0
  275. package/templates/shop/README.md +102 -0
  276. package/templates/shop/app/auth-form.tsx +129 -0
  277. package/templates/shop/app/dashboard/dashboard-client.tsx +264 -0
  278. package/templates/shop/app/dashboard/page.tsx +59 -0
  279. package/templates/shop/app/error.tsx +26 -0
  280. package/templates/shop/app/globals.css +148 -0
  281. package/templates/shop/app/layout.tsx +160 -0
  282. package/templates/shop/app/login/page.tsx +39 -0
  283. package/templates/shop/app/not-found.tsx +19 -0
  284. package/templates/shop/app/page.tsx +95 -0
  285. package/templates/shop/app/robots.ts +12 -0
  286. package/templates/shop/app/shop-client.tsx +436 -0
  287. package/templates/shop/app/sitemap.ts +9 -0
  288. package/templates/shop/app/success/page.tsx +33 -0
  289. package/templates/shop/app.ts +134 -0
  290. package/templates/shop/components/marketing.tsx +96 -0
  291. package/templates/shop/components/section-scroller.tsx +35 -0
  292. package/templates/shop/components/ui/button.tsx +56 -0
  293. package/templates/shop/components/ui/card.tsx +90 -0
  294. package/templates/shop/components.json +20 -0
  295. package/templates/shop/functions/cancelOrder.ts +33 -0
  296. package/templates/shop/functions/checkout.ts +130 -0
  297. package/templates/shop/functions/fulfillOrder.ts +17 -0
  298. package/templates/shop/functions/markGroupPaid.ts +26 -0
  299. package/templates/shop/functions/ordersForOwner.ts +28 -0
  300. package/templates/shop/functions/releaseGroup.ts +36 -0
  301. package/templates/shop/functions/reserveCart.ts +87 -0
  302. package/templates/shop/functions/restockProduct.ts +23 -0
  303. package/templates/shop/functions/seedProducts.ts +30 -0
  304. package/templates/shop/functions/stripeWebhook.ts +72 -0
  305. package/templates/shop/gitignore +10 -0
  306. package/templates/shop/lib/owner.ts +26 -0
  307. package/templates/shop/lib/shop.ts +45 -0
  308. package/templates/shop/lib/site.config.ts +198 -0
  309. package/templates/shop/lib/utils.ts +10 -0
  310. package/templates/shop/package.json +35 -0
  311. package/templates/shop/tsconfig.json +18 -0
  312. package/templates/waitlist/.env.example +12 -0
  313. package/templates/waitlist/AGENTS.md +61 -0
  314. package/templates/waitlist/README.md +81 -0
  315. package/templates/waitlist/app/auth-form.tsx +129 -0
  316. package/templates/waitlist/app/dashboard/dashboard-client.tsx +297 -0
  317. package/templates/waitlist/app/dashboard/page.tsx +70 -0
  318. package/templates/waitlist/app/error.tsx +26 -0
  319. package/templates/waitlist/app/globals.css +148 -0
  320. package/templates/waitlist/app/layout.tsx +158 -0
  321. package/templates/waitlist/app/login/page.tsx +39 -0
  322. package/templates/waitlist/app/not-found.tsx +19 -0
  323. package/templates/waitlist/app/page.tsx +119 -0
  324. package/templates/waitlist/app/robots.ts +12 -0
  325. package/templates/waitlist/app/sitemap.ts +9 -0
  326. package/templates/waitlist/app/waitlist-hero.tsx +219 -0
  327. package/templates/waitlist/app.ts +134 -0
  328. package/templates/waitlist/components/marketing.tsx +96 -0
  329. package/templates/waitlist/components/ui/button.tsx +56 -0
  330. package/templates/waitlist/components/ui/card.tsx +90 -0
  331. package/templates/waitlist/components.json +20 -0
  332. package/templates/waitlist/functions/joinWaitlist.ts +82 -0
  333. package/templates/waitlist/functions/waitlistStats.ts +75 -0
  334. package/templates/waitlist/gitignore +10 -0
  335. package/templates/waitlist/lib/owner.ts +26 -0
  336. package/templates/waitlist/lib/site.config.ts +178 -0
  337. package/templates/waitlist/lib/stats.ts +30 -0
  338. package/templates/waitlist/lib/utils.ts +10 -0
  339. package/templates/waitlist/package.json +34 -0
  340. package/templates/waitlist/tsconfig.json +18 -0
@@ -13,19 +13,18 @@ import {
13
13
  Portrait,
14
14
  Terminal,
15
15
  } from "@/components/marketing";
16
- import { PRODUCTS, productBySlug } from "@/lib/products";
16
+ import { siteConfig, productBySlug, type Product } from "@/lib/site.config";
17
17
 
18
18
  // SEO metadata. Exported `metadata` is rendered into <head> on the server, so
19
19
  // this marketing page is fully indexable — view source and the copy is in the
20
- // HTML. Swap "Acme" for your product throughout.
20
+ // HTML. All copy lives in lib/site.config.ts; edit it there.
21
21
  export const metadata: Metadata = {
22
- title: "Acme — the workspace where work gets done",
23
- description:
24
- "Acme brings your projects, your people, and your updates into one fast, real-time workspace. Plan together, ship together, keep everyone in the loop.",
22
+ title: siteConfig.seo.title,
23
+ description: siteConfig.seo.description,
25
24
  };
26
25
 
27
- // The three products the homepage features inline. Each links to its own
28
- // /products/[slug] page for the full story. (Defined once in lib/products.ts.)
26
+ // The products the homepage features inline. Each links to its own
27
+ // /products/[slug] page for the full story. (Defined once in lib/site.config.ts.)
29
28
  const projects = productBySlug("projects")!;
30
29
  const tasks = productBySlug("tasks")!;
31
30
  const docs = productBySlug("docs")!;
@@ -34,24 +33,39 @@ const automations = productBySlug("automations")!;
34
33
  // `app/page.tsx` → `/`. A server-rendered marketing landing page. It reads
35
34
  // `auth` (resolved from the session cookie during the render) so the call to
36
35
  // action is right on the first byte — "Get started" for visitors, "Open
37
- // dashboard" once you're signed in. No client fetch, no flash.
36
+ // dashboard" once you're signed in. No client fetch, no flash. Every string is
37
+ // sourced from `siteConfig` so the whole page rebrands from one file.
38
38
  export default function LandingPage({ auth }: PageProps) {
39
39
  const signedIn = Boolean(auth.user_id);
40
40
  const primaryHref = signedIn ? "/dashboard" : "/signup";
41
41
  const primaryLabel = signedIn ? "Open dashboard" : "Get started";
42
42
 
43
+ const {
44
+ hero,
45
+ logoCloud,
46
+ outcomes,
47
+ featuredTestimonial,
48
+ entryPoints,
49
+ engagement,
50
+ customers,
51
+ gettingStarted,
52
+ pricing,
53
+ team,
54
+ finalCta,
55
+ faq,
56
+ brand,
57
+ } = siteConfig;
58
+
43
59
  return (
44
60
  <div className="bg-white text-zinc-900">
45
61
  {/* ============================ HERO ============================ */}
46
62
  <section className={`${WRAP} pt-20 pb-16 sm:pt-28`}>
47
- <Badge>Acme for teams is here →</Badge>
63
+ <Badge>{hero.badge}</Badge>
48
64
  <h1 className="mt-6 max-w-2xl text-balance text-[2.75rem] font-semibold leading-[1.05] tracking-[-0.02em] sm:text-[3.5rem]">
49
- The workspace where work gets done.
65
+ {hero.headline}
50
66
  </h1>
51
67
  <p className="mt-6 max-w-xl text-[17px] leading-relaxed text-zinc-500">
52
- Acme brings your projects, your people, and your updates into one
53
- fast, real-time workspace. Plan together, ship together, and keep
54
- everyone in the loop without the busywork.
68
+ {hero.subcopy}
55
69
  </p>
56
70
  <div className="mt-8 flex flex-wrap items-center gap-4">
57
71
  <PrimaryButton href={primaryHref}>{primaryLabel}</PrimaryButton>
@@ -59,30 +73,28 @@ export default function LandingPage({ auth }: PageProps) {
59
73
  </div>
60
74
 
61
75
  <div className="mt-16">
62
- <Shot url="acme.app/dashboard" label="Dashboard preview" />
76
+ <Shot url={`${brand.domain}/dashboard`} label={hero.mockupLabel} />
63
77
  </div>
64
78
  </section>
65
79
 
66
80
  {/* ========================= LOGO CLOUD ========================= */}
67
81
  <section className={`${WRAP} pb-16`}>
68
82
  <p className="font-mono text-[11px] uppercase tracking-[0.14em] text-zinc-400">
69
- Powering fast-moving teams
83
+ {logoCloud.label}
70
84
  </p>
71
85
  <div className="mt-6 flex flex-wrap items-center gap-x-10 gap-y-4">
72
- {["Northwind", "Globex", "Initech", "Umbrella", "Soylent", "Hooli"].map(
73
- (name) => (
74
- <div
75
- key={name}
76
- className="flex items-center gap-2 text-zinc-400"
77
- title={name}
78
- >
79
- <span className="size-5 rounded bg-zinc-200" />
80
- <span className="text-[13px] font-semibold uppercase tracking-wide">
81
- {name}
82
- </span>
83
- </div>
84
- ),
85
- )}
86
+ {logoCloud.companies.map((name) => (
87
+ <div
88
+ key={name}
89
+ className="flex items-center gap-2 text-zinc-400"
90
+ title={name}
91
+ >
92
+ <span className="size-5 rounded bg-zinc-200" />
93
+ <span className="text-[13px] font-semibold uppercase tracking-wide">
94
+ {name}
95
+ </span>
96
+ </div>
97
+ ))}
86
98
  </div>
87
99
  </section>
88
100
 
@@ -91,17 +103,15 @@ export default function LandingPage({ auth }: PageProps) {
91
103
  <section className={`${WRAP} py-20`}>
92
104
  <div className="grid gap-12 lg:grid-cols-[0.9fr_1.1fr]">
93
105
  <div>
94
- <Eyebrow>Why Acme</Eyebrow>
106
+ <Eyebrow>{outcomes.eyebrow}</Eyebrow>
95
107
  <h2 className="mt-4 text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
96
- Everything your team needs to stay in motion.
108
+ {outcomes.headline}
97
109
  </h2>
98
110
  <p className="mt-5 max-w-md text-[15px] leading-relaxed text-zinc-500">
99
- Most teams lose work somewhere between the kickoff and the ship
100
- date. Acme keeps the whole path in one place, so every idea has a
101
- clear route from planned, to in progress, to done.
111
+ {outcomes.body}
102
112
  </p>
103
113
  </div>
104
- <FeatureGrid columns={2} items={OUTCOMES} />
114
+ <FeatureGrid columns={2} items={outcomes.items} />
105
115
  </div>
106
116
  </section>
107
117
 
@@ -109,20 +119,20 @@ export default function LandingPage({ auth }: PageProps) {
109
119
  <Divider />
110
120
  <section className={`${WRAP} py-20`}>
111
121
  <div className="grid items-center gap-12 lg:grid-cols-[0.8fr_1.2fr]">
112
- <Portrait name="Maya Chen" />
122
+ <Portrait name={featuredTestimonial.name} />
113
123
  <figure>
114
124
  <div className="font-serif text-4xl leading-none text-brand">
115
125
  &ldquo;
116
126
  </div>
117
127
  <blockquote className="mt-4 text-balance text-2xl font-medium leading-[1.35] tracking-[-0.01em] sm:text-[1.75rem]">
118
- Our whole team finally works in one place. Acme made it easy to see
119
- what is happening, decide what is next, and keep everyone moving in
120
- the same direction.
128
+ {featuredTestimonial.quote}
121
129
  </blockquote>
122
130
  <figcaption className="mt-8 border-t border-zinc-200/70 pt-6">
123
- <div className="text-sm font-semibold">Maya Chen</div>
131
+ <div className="text-sm font-semibold">
132
+ {featuredTestimonial.name}
133
+ </div>
124
134
  <div className="text-sm text-zinc-500">
125
- Head of Product, Northwind
135
+ {featuredTestimonial.role}
126
136
  </div>
127
137
  </figcaption>
128
138
  </figure>
@@ -137,12 +147,12 @@ export default function LandingPage({ auth }: PageProps) {
137
147
  <Divider />
138
148
  <section className={`${WRAP} py-20`}>
139
149
  <SectionHead
140
- eyebrow="Anywhere"
141
- title="Meet your team where they already are."
142
- body="Web, desktop, and a typed API all share the same workspace underneath, so nothing lives in two places."
150
+ eyebrow={entryPoints.eyebrow}
151
+ title={entryPoints.title}
152
+ body={entryPoints.body}
143
153
  />
144
154
  <div className="mt-12 grid gap-5 sm:grid-cols-2">
145
- {ENTRY_POINTS.map((c, i) => (
155
+ {entryPoints.items.map((c, i) => (
146
156
  <div
147
157
  key={c.title}
148
158
  className="rounded-2xl border border-zinc-200 bg-paper p-7"
@@ -175,29 +185,18 @@ export default function LandingPage({ auth }: PageProps) {
175
185
  {/* ============== ENGAGEMENT (prose + numbered) ============== */}
176
186
  <Divider />
177
187
  <section className={`${WRAP} py-20`}>
178
- <Eyebrow>Momentum</Eyebrow>
188
+ <Eyebrow>{engagement.eyebrow}</Eyebrow>
179
189
  <h2 className="mt-4 max-w-2xl text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
180
- Most tools go quiet after the kickoff.
190
+ {engagement.headline}
181
191
  </h2>
182
192
  <div className="mt-12 grid gap-12 lg:grid-cols-2">
183
193
  <div className="space-y-5 text-[15px] leading-relaxed text-zinc-500">
184
- <p>
185
- Someone shares an idea, it lands in a list, and that is the last
186
- anyone hears of it. Acme treats every idea as the start of a loop,
187
- not the end of one.
188
- </p>
189
- <p>
190
- When the status moves to planned, the people who care hear about
191
- it. When it ships, they hear about it first. And every week a
192
- digest pulls them back with the work worth weighing in on.
193
- </p>
194
- <p>
195
- None of it is something you configure. Turn Acme on, and the loop
196
- starts running the same day.
197
- </p>
194
+ {engagement.paragraphs.map((p) => (
195
+ <p key={p}>{p}</p>
196
+ ))}
198
197
  </div>
199
198
  <ol className="space-y-7">
200
- {ENGAGEMENT.map((e, i) => (
199
+ {engagement.items.map((e, i) => (
201
200
  <li key={e.title} className="flex gap-4">
202
201
  <span className="mt-0.5 font-mono text-[11px] text-zinc-300">
203
202
  0{i + 1}
@@ -228,7 +227,7 @@ export default function LandingPage({ auth }: PageProps) {
228
227
  <FeatureGrid className="mt-14" items={automations.features} />
229
228
  <div className="mt-8">
230
229
  <GhostLink href="/products/automations">
231
- Explore Automations
230
+ Explore {automations.title}
232
231
  </GhostLink>
233
232
  </div>
234
233
  <div className="mt-12">
@@ -240,12 +239,12 @@ export default function LandingPage({ auth }: PageProps) {
240
239
  <Divider />
241
240
  <section id="customers" className={`${WRAP} py-20`}>
242
241
  <SectionHead
243
- eyebrow="Customers"
244
- title="Teams that ship with Acme."
245
- body="A few words from the people who run their work in Acme every day."
242
+ eyebrow={customers.eyebrow}
243
+ title={customers.title}
244
+ body={customers.body}
246
245
  />
247
246
  <div className="mt-12 grid gap-5 sm:grid-cols-3">
248
- {QUOTES.map((q) => (
247
+ {customers.quotes.map((q) => (
249
248
  <figure
250
249
  key={q.name + q.role}
251
250
  className="flex flex-col rounded-2xl border border-zinc-200 bg-paper p-6"
@@ -270,19 +269,18 @@ export default function LandingPage({ auth }: PageProps) {
270
269
  {/* ===================== GETTING STARTED ==================== */}
271
270
  <Divider />
272
271
  <section className={`${WRAP} py-20`}>
273
- <Eyebrow>Get started</Eyebrow>
272
+ <Eyebrow>{gettingStarted.eyebrow}</Eyebrow>
274
273
  <h2 className="mt-4 max-w-xl text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
275
- Up and running in 60 seconds.
274
+ {gettingStarted.headline}
276
275
  </h2>
277
276
  <p className="mt-5 max-w-md text-[15px] leading-relaxed text-zinc-500">
278
- No credit card, no sales call, no setup wizard. An email and a
279
- workspace name are all it takes to start.
277
+ {gettingStarted.body}
280
278
  </p>
281
279
  <div className="mt-8">
282
280
  <PrimaryButton href={primaryHref}>{primaryLabel}</PrimaryButton>
283
281
  </div>
284
282
  <ol className="mt-14 max-w-xl space-y-8">
285
- {STEPS.map((s, i) => (
283
+ {gettingStarted.steps.map((s, i) => (
286
284
  <li key={s.title} className="flex gap-5">
287
285
  <span className="flex size-7 shrink-0 items-center justify-center rounded-full bg-brand-soft font-mono text-[11px] text-brand">
288
286
  0{i + 1}
@@ -301,16 +299,15 @@ export default function LandingPage({ auth }: PageProps) {
301
299
  {/* ========================= PRICING ======================== */}
302
300
  <Divider />
303
301
  <section id="pricing" className={`${WRAP} py-20`}>
304
- <Eyebrow>Pricing</Eyebrow>
302
+ <Eyebrow>{pricing.eyebrow}</Eyebrow>
305
303
  <h2 className="mt-4 max-w-xl text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
306
- Simple pricing. Every plan.
304
+ {pricing.headline}
307
305
  </h2>
308
306
  <p className="mt-5 max-w-md text-[15px] leading-relaxed text-zinc-500">
309
- Start free and upgrade when your team grows. No per-seat surprises, no
310
- annual lock-in.
307
+ {pricing.body}
311
308
  </p>
312
309
  <div className="mt-12 grid gap-5 lg:grid-cols-3">
313
- {PLANS.map((p) => (
310
+ {pricing.plans.map((p) => (
314
311
  <div
315
312
  key={p.name}
316
313
  className={`flex flex-col rounded-2xl border p-7 ${
@@ -369,54 +366,47 @@ export default function LandingPage({ auth }: PageProps) {
369
366
  <section className={`${WRAP} py-20`}>
370
367
  <div className="grid gap-12 lg:grid-cols-[0.9fr_1.1fr]">
371
368
  <div>
372
- <Eyebrow>The team</Eyebrow>
369
+ <Eyebrow>{team.eyebrow}</Eyebrow>
373
370
  <h2 className="mt-4 text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
374
- Built by people who use it every day.
371
+ {team.headline}
375
372
  </h2>
376
373
  <p className="mt-5 max-w-md text-[15px] leading-relaxed text-zinc-500">
377
- Acme is built by a small team that got tired of clunky, overpriced
378
- tools. Every feature earns its place by being something worth using
379
- every day.
374
+ {team.body}
380
375
  </p>
381
376
  </div>
382
- <FeatureGrid columns={2} items={TEAM} />
377
+ <FeatureGrid columns={2} items={team.items} />
383
378
  </div>
384
379
  </section>
385
380
 
386
381
  {/* ======================= FINAL CTA ======================== */}
387
382
  <Divider />
388
383
  <section className={`${WRAP} py-24`}>
389
- <Eyebrow>Start building</Eyebrow>
384
+ <Eyebrow>{finalCta.eyebrow}</Eyebrow>
390
385
  <h2 className="mt-4 max-w-xl text-balance text-[2.5rem] font-semibold leading-[1.05] tracking-[-0.02em] sm:text-[3rem]">
391
- Stop losing momentum to busywork.
386
+ {finalCta.headline}
392
387
  </h2>
393
388
  <p className="mt-6 max-w-lg text-[16px] leading-relaxed text-zinc-500">
394
- When your team can see the work, decide what is next, and ship in one
395
- place, momentum takes care of itself. This is what{" "}
389
+ {finalCta.bodyLead}
396
390
  <span className="rounded bg-brand-soft px-1.5 py-0.5 font-medium text-brand">
397
- working in flow
398
- </span>{" "}
399
- looks like.
391
+ {finalCta.highlight}
392
+ </span>
393
+ {finalCta.bodyTail}
400
394
  </p>
401
395
  <div className="mt-8">
402
- <PrimaryButton href={primaryHref}>
403
- Start building with Acme
404
- </PrimaryButton>
396
+ <PrimaryButton href={primaryHref}>{finalCta.cta}</PrimaryButton>
405
397
  </div>
406
- <p className="mt-4 text-[12px] text-zinc-400">
407
- Free to start · No credit card · Cancel anytime
408
- </p>
398
+ <p className="mt-4 text-[12px] text-zinc-400">{finalCta.footnote}</p>
409
399
  </section>
410
400
 
411
401
  {/* ========================== FAQ =========================== */}
412
402
  <Divider />
413
403
  <section id="faq" className={`${WRAP} py-20`}>
414
- <Eyebrow>Questions</Eyebrow>
404
+ <Eyebrow>{faq.eyebrow}</Eyebrow>
415
405
  <h2 className="mt-4 text-balance text-3xl font-semibold leading-[1.1] tracking-[-0.02em] sm:text-[2.5rem]">
416
- Frequently asked.
406
+ {faq.headline}
417
407
  </h2>
418
408
  <div className="mt-10 divide-y divide-zinc-200/70 border-y border-zinc-200/70">
419
- {FAQ.map((f) => (
409
+ {faq.items.map((f) => (
420
410
  <details key={f.q} className="group py-5">
421
411
  <summary className="flex cursor-pointer items-center justify-between text-[15px] font-medium text-zinc-900 marker:hidden [&::-webkit-details-marker]:hidden">
422
412
  {f.q}
@@ -442,7 +432,7 @@ function ProductSection({
442
432
  primaryHref,
443
433
  id,
444
434
  }: {
445
- product: (typeof PRODUCTS)[number];
435
+ product: Product;
446
436
  primaryHref: string;
447
437
  id?: string;
448
438
  }) {
@@ -477,177 +467,3 @@ function initials(name: string) {
477
467
  .slice(0, 2)
478
468
  .toUpperCase();
479
469
  }
480
-
481
- /* ---------------------------------------------------------------- */
482
- /* Homepage-specific content — fictional demo copy; swap for yours. */
483
- /* ---------------------------------------------------------------- */
484
-
485
- const OUTCOMES = [
486
- {
487
- title: "Work in one place",
488
- body: "Plans, tasks, and docs live together, so nothing gets lost between tools.",
489
- },
490
- {
491
- title: "Clear priorities",
492
- body: "Everyone can see what is planned, in progress, and done — and why.",
493
- },
494
- {
495
- title: "Real-time by default",
496
- body: "Every change syncs instantly, so the workspace is the same on every screen.",
497
- },
498
- {
499
- title: "Less busywork",
500
- body: "Automations handle the routine, so your team focuses on the work that matters.",
501
- },
502
- ];
503
-
504
- const ENTRY_POINTS = [
505
- {
506
- icon: "◇",
507
- title: "Cloud workspace",
508
- body: "Your whole team works in the browser. Nothing to install, always up to date, and secure by default.",
509
- },
510
- {
511
- icon: "◆",
512
- title: "Open API",
513
- body: "A typed API and webhooks for everything in Acme, so you can wire it into the rest of your stack.",
514
- },
515
- ];
516
-
517
- const ENGAGEMENT = [
518
- {
519
- title: "The loop",
520
- body: "Submission, acknowledgment, progress, launch. Four moments every person gets to feel heard.",
521
- },
522
- {
523
- title: "Instant alerts",
524
- body: "The moment someone votes or comments on their idea, social proof brings them back.",
525
- },
526
- {
527
- title: "Launch alerts",
528
- body: "The note that tells a person the thing they asked for just shipped. Nothing builds loyalty faster.",
529
- },
530
- {
531
- title: "Weekly digest",
532
- body: "The top ideas across your boards, delivered every week, with a one-click way to weigh in.",
533
- },
534
- ];
535
-
536
- const QUOTES = [
537
- {
538
- quote:
539
- "We finally have one source of truth for the work. The whole team can see what is happening without a status meeting.",
540
- name: "Daniel Reyes",
541
- role: "Founder, Globex",
542
- },
543
- {
544
- quote:
545
- "Acme noticeably improved how we plan. Instead of piecing together five tools, we have one hub for everything.",
546
- name: "Priya Sharma",
547
- role: "Founder, OpenLane",
548
- },
549
- {
550
- quote:
551
- "Ever since we added Acme, people actually feel heard. It has helped us build a loyal community of users.",
552
- name: "Marcus Bell",
553
- role: "Cofounder, Initech",
554
- },
555
- ];
556
-
557
- const STEPS = [
558
- {
559
- title: "Create a workspace",
560
- body: "Sign up with just an email. Pick a name. That is the entire form.",
561
- },
562
- {
563
- title: "Invite your team",
564
- body: "Add teammates, share the board URL, or link it from your site. Work starts flowing in.",
565
- },
566
- {
567
- title: "Watch the loop start",
568
- body: "People add ideas, votes pile up, you ship, and everyone hears about it and comes back with more.",
569
- },
570
- ];
571
-
572
- const PLANS = [
573
- {
574
- name: "Free",
575
- tagline: "For getting started.",
576
- price: "$0",
577
- unit: "forever",
578
- cta: "Get started",
579
- featured: false,
580
- features: [
581
- "Up to 3 projects",
582
- "Unlimited members",
583
- "Real-time board",
584
- "Community support",
585
- ],
586
- },
587
- {
588
- name: "Team",
589
- tagline: "For small teams.",
590
- price: "$29",
591
- unit: "/ month",
592
- cta: "Start free trial",
593
- featured: true,
594
- features: [
595
- "Unlimited projects",
596
- "Roadmap and updates",
597
- "Private boards",
598
- "Priority support",
599
- ],
600
- },
601
- {
602
- name: "Business",
603
- tagline: "For growing teams.",
604
- price: "$59",
605
- unit: "/ month",
606
- cta: "Start free trial",
607
- featured: false,
608
- features: [
609
- "Everything in Team",
610
- "SSO and audit log",
611
- "Custom domain",
612
- "Onboarding help",
613
- ],
614
- },
615
- ];
616
-
617
- const TEAM = [
618
- {
619
- title: "A small team",
620
- body: "No committees. Every feature ships because someone decided it was worth building.",
621
- },
622
- {
623
- title: "Design first",
624
- body: "Beautiful software makes people want to use it. Every screen is built with that in mind.",
625
- },
626
- {
627
- title: "Ships every week",
628
- body: "Updates go out weekly, often based on work posted directly to our own board.",
629
- },
630
- {
631
- title: "Customer funded",
632
- body: "We optimize for your renewal, not an exit. If Acme works for you, it works for us.",
633
- },
634
- ];
635
-
636
- const FAQ = [
637
- {
638
- q: "Is Acme a fit for my team?",
639
- a: "Acme works for any team that plans and ships work together — product, design, engineering, or ops.",
640
- },
641
- {
642
- q: "What about migrating from another tool?",
643
- a: "Import your existing projects and pick up where you left off.",
644
- },
645
- {
646
- q: "Is there an API or a way to script this?",
647
- a: "Yes — every action in Acme is available over a typed API and an MCP server.",
648
- },
649
- {
650
- q: "Do you offer SSO?",
651
- a: "SSO and audit logging are included on the Business plan.",
652
- },
653
- ];
@@ -1,122 +1,9 @@
1
- // Single source of truth for the marketing "products". The nav dropdown, the
2
- // homepage feature sections, and the /products/[slug] pages all read from here,
3
- // so a product is defined once. Add an entry and it shows up everywhere.
4
- // Fictional demo copy — rename these to your real product modules.
5
-
6
- export type ProductFeature = { title: string; body: string };
7
-
8
- export type Product = {
9
- slug: string;
10
- icon: string;
11
- title: string; // nav label + page <h1> subject
12
- tagline: string; // one-line blurb for the nav dropdown
13
- eyebrow: string; // section/page eyebrow
14
- headline: string; // page hero headline
15
- summary: string; // page hero paragraph
16
- features: ProductFeature[];
17
- mockupUrl: string; // fake browser URL in the screenshot frame
18
- mockupLabel: string; // placeholder label inside the frame
19
- };
20
-
21
- export const PRODUCTS: Product[] = [
22
- {
23
- slug: "projects",
24
- icon: "▤",
25
- title: "Projects",
26
- tagline: "Plan and track every initiative.",
27
- eyebrow: "Projects",
28
- headline: "Plan every project in one place.",
29
- summary:
30
- "Give your team one place to plan the work, see what is in flight, and keep every project moving toward done.",
31
- mockupUrl: "acme.app/projects",
32
- mockupLabel: "Projects board",
33
- features: [
34
- { title: "Flexible views", body: "See the work as a board, a list, or a timeline — whatever fits the team." },
35
- { title: "Milestones", body: "Group work into milestones so everyone knows what ships next." },
36
- { title: "Dependencies", body: "Link related work so blockers surface before they bite." },
37
- { title: "Custom fields", body: "Track the details that matter to your team, your way." },
38
- { title: "Templates", body: "Start new projects from a template instead of a blank page." },
39
- { title: "Saved filters", body: "Slice the work by owner, status, or label in a single click." },
40
- ],
41
- },
42
- {
43
- slug: "tasks",
44
- icon: "✓",
45
- title: "Tasks",
46
- tagline: "Assign, prioritize, and finish work.",
47
- eyebrow: "Tasks",
48
- headline: "Turn plans into finished work.",
49
- summary:
50
- "Break projects into tasks, assign owners, and watch progress update in real time across every screen.",
51
- mockupUrl: "acme.app/tasks",
52
- mockupLabel: "Task list",
53
- features: [
54
- { title: "Assignees and due dates", body: "Every task has a clear owner and a clear deadline." },
55
- { title: "Subtasks", body: "Break big tasks into small, checkable steps." },
56
- { title: "Priorities", body: "Sort by what matters most so the right work happens first." },
57
- { title: "Comments", body: "Discuss the work where it lives, with full context attached." },
58
- { title: "My work", body: "A personal view of everything on your plate, across projects." },
59
- { title: "Recurring tasks", body: "Set it once and the task comes back when it should." },
60
- ],
61
- },
62
- {
63
- slug: "docs",
64
- icon: "≡",
65
- title: "Docs",
66
- tagline: "Write and share team knowledge.",
67
- eyebrow: "Docs",
68
- headline: "Keep what your team knows in one place.",
69
- summary:
70
- "Write docs, notes, and specs alongside the work, so the context never lives in just one person's head.",
71
- mockupUrl: "acme.app/docs",
72
- mockupLabel: "Doc editor",
73
- features: [
74
- { title: "Rich editor", body: "Headings, checklists, tables, and embeds in a clean editor." },
75
- { title: "Linked to work", body: "Connect a doc to the project or task it describes." },
76
- { title: "Real-time co-editing", body: "Write together, with changes syncing as you type." },
77
- { title: "Version history", body: "Roll back to any earlier version in a click." },
78
- { title: "Templates", body: "Spin up specs, briefs, and notes from reusable templates." },
79
- { title: "Instant search", body: "Find any doc by title or content in milliseconds." },
80
- ],
81
- },
82
- {
83
- slug: "automations",
84
- icon: "⟳",
85
- title: "Automations",
86
- tagline: "Automate the busywork.",
87
- eyebrow: "Automations",
88
- headline: "Let the routine work run itself.",
89
- summary:
90
- "Build simple rules that move work forward automatically, so your team spends its time on what actually matters.",
91
- mockupUrl: "acme.app/automations",
92
- mockupLabel: "Automation builder",
93
- features: [
94
- { title: "Rules", body: "When this happens, do that — no code required." },
95
- { title: "Scheduled runs", body: "Kick off routine work on a schedule you set." },
96
- { title: "Webhooks", body: "Trigger automations from anything that can send a request." },
97
- { title: "Run history", body: "See exactly what ran, when, and why." },
98
- ],
99
- },
100
- {
101
- slug: "analytics",
102
- icon: "◔",
103
- title: "Analytics",
104
- tagline: "Measure what actually matters.",
105
- eyebrow: "Analytics",
106
- headline: "See how the work is really going.",
107
- summary:
108
- "Track throughput, cycle time, and progress across projects, so you can spot what is stuck before it slips.",
109
- mockupUrl: "acme.app/analytics",
110
- mockupLabel: "Analytics dashboard",
111
- features: [
112
- { title: "Dashboards", body: "Build views that answer the questions your team asks most." },
113
- { title: "Cycle time", body: "See how long work takes from start to done." },
114
- { title: "Throughput", body: "Track how much ships each week, by team or project." },
115
- { title: "Exports", body: "Send any view to CSV or your warehouse." },
116
- ],
117
- },
118
- ];
119
-
120
- export function productBySlug(slug: string): Product | undefined {
121
- return PRODUCTS.find((p) => p.slug === slug);
122
- }
1
+ // The marketing "products" now live in the single site config so the whole
2
+ // template can be rebranded from one file. This module re-exports them so
3
+ // existing imports (`@/lib/products`) keep working. Edit lib/site.config.ts.
4
+ export {
5
+ PRODUCTS,
6
+ productBySlug,
7
+ type Product,
8
+ type ProductFeature,
9
+ } from "./site.config";