@wopr-network/platform-ui-core 1.0.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 (543) hide show
  1. package/.env.paperclip +18 -0
  2. package/.env.wopr +18 -0
  3. package/README.md +36 -0
  4. package/biome.json +52 -0
  5. package/next.config.ts +45 -0
  6. package/package.json +84 -0
  7. package/postcss.config.mjs +7 -0
  8. package/public/file.svg +1 -0
  9. package/public/globe.svg +1 -0
  10. package/public/window.svg +1 -0
  11. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +741 -0
  12. package/src/__tests__/account-page-redirect.test.tsx +73 -0
  13. package/src/__tests__/account-switcher.test.tsx +85 -0
  14. package/src/__tests__/activity-page.test.tsx +176 -0
  15. package/src/__tests__/add-payment-method-dialog.test.tsx +160 -0
  16. package/src/__tests__/admin-api.test.ts +244 -0
  17. package/src/__tests__/admin-gpu-api.test.ts +188 -0
  18. package/src/__tests__/admin-guard.test.tsx +79 -0
  19. package/src/__tests__/admin-marketplace-api.test.ts +179 -0
  20. package/src/__tests__/admin-middleware.test.ts +157 -0
  21. package/src/__tests__/admin-tenant-table.test.tsx +95 -0
  22. package/src/__tests__/affiliate-dashboard.test.tsx +178 -0
  23. package/src/__tests__/api-401-redirect.test.ts +78 -0
  24. package/src/__tests__/api-client.test.ts +316 -0
  25. package/src/__tests__/api-config.test.ts +89 -0
  26. package/src/__tests__/api-control-instance.test.ts +69 -0
  27. package/src/__tests__/api-fleet-resources.test.ts +52 -0
  28. package/src/__tests__/api-fleet-trpc.test.ts +252 -0
  29. package/src/__tests__/api-get-instance-config.test.ts +41 -0
  30. package/src/__tests__/api-null-guards.test.ts +244 -0
  31. package/src/__tests__/api-rename-instance.test.ts +60 -0
  32. package/src/__tests__/api-update-instance-config.test.ts +60 -0
  33. package/src/__tests__/audit-log-table-pagination.test.tsx +136 -0
  34. package/src/__tests__/auth-client.test.ts +87 -0
  35. package/src/__tests__/auth-password-reset.test.tsx +435 -0
  36. package/src/__tests__/auth-redirect.test.tsx +60 -0
  37. package/src/__tests__/auth.test.tsx +269 -0
  38. package/src/__tests__/auto-topup-card.test.tsx +257 -0
  39. package/src/__tests__/backups-tab.test.tsx +221 -0
  40. package/src/__tests__/billing-byok-callout.test.tsx +76 -0
  41. package/src/__tests__/billing-layout-nav-hidden.test.tsx +47 -0
  42. package/src/__tests__/billing-payment-org-invoices.test.tsx +123 -0
  43. package/src/__tests__/billing.test.tsx +509 -0
  44. package/src/__tests__/bot-settings/resources-tab.test.tsx +119 -0
  45. package/src/__tests__/bot-settings/storage-tab.test.tsx +80 -0
  46. package/src/__tests__/bot-settings/vps-info-panel.test.tsx +108 -0
  47. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +52 -0
  48. package/src/__tests__/bot-settings-data-control.test.ts +49 -0
  49. package/src/__tests__/bot-settings-restart.test.tsx +149 -0
  50. package/src/__tests__/bot-settings.test.tsx +678 -0
  51. package/src/__tests__/brand.test.ts +335 -0
  52. package/src/__tests__/buy-credits-panel.test.tsx +249 -0
  53. package/src/__tests__/buy-crypto-credits-panel.test.tsx +178 -0
  54. package/src/__tests__/capability-conflicts.test.ts +88 -0
  55. package/src/__tests__/capability-resolver.test.tsx +173 -0
  56. package/src/__tests__/changeset-detail.test.tsx +156 -0
  57. package/src/__tests__/channel-setup-logger.test.ts +22 -0
  58. package/src/__tests__/channel-setup-toast.test.tsx +60 -0
  59. package/src/__tests__/channel-wizard.test.tsx +505 -0
  60. package/src/__tests__/chat/ambient-dot.test.tsx +35 -0
  61. package/src/__tests__/chat/chat-input.test.tsx +78 -0
  62. package/src/__tests__/chat/chat-message.test.tsx +45 -0
  63. package/src/__tests__/chat/chat-panel.test.tsx +111 -0
  64. package/src/__tests__/chat/chat-widget.test.tsx +82 -0
  65. package/src/__tests__/chat-store.test.ts +87 -0
  66. package/src/__tests__/command-center.test.tsx +246 -0
  67. package/src/__tests__/compliance-retention-edit.test.tsx +134 -0
  68. package/src/__tests__/coupon-input.test.tsx +119 -0
  69. package/src/__tests__/create-instance.test.tsx +96 -0
  70. package/src/__tests__/create-org-wizard.test.tsx +200 -0
  71. package/src/__tests__/credit-balance.test.tsx +103 -0
  72. package/src/__tests__/credits.test.tsx +376 -0
  73. package/src/__tests__/csrf-middleware.test.ts +198 -0
  74. package/src/__tests__/degraded-state-banner.test.tsx +130 -0
  75. package/src/__tests__/dividend-calculator.test.tsx +20 -0
  76. package/src/__tests__/dividend-stats.test.tsx +64 -0
  77. package/src/__tests__/dividend.test.tsx +169 -0
  78. package/src/__tests__/dockerfile.test.ts +110 -0
  79. package/src/__tests__/email-verification-banner.test.tsx +64 -0
  80. package/src/__tests__/env-example.test.ts +25 -0
  81. package/src/__tests__/error-boundaries.test.tsx +64 -0
  82. package/src/__tests__/fetch-pricing.test.ts +121 -0
  83. package/src/__tests__/field-oauth.test.tsx +302 -0
  84. package/src/__tests__/fixtures/mock-manifests-data.js +372 -0
  85. package/src/__tests__/fixtures/mock-manifests.ts +24 -0
  86. package/src/__tests__/fleet-health-timestamp.test.tsx +101 -0
  87. package/src/__tests__/fleet-health-update.test.tsx +83 -0
  88. package/src/__tests__/format-credit.test.ts +58 -0
  89. package/src/__tests__/gpu-dashboard.test.tsx +236 -0
  90. package/src/__tests__/hosted-usage-date-range.test.tsx +54 -0
  91. package/src/__tests__/instance-detail.test.tsx +571 -0
  92. package/src/__tests__/instance-list.test.tsx +230 -0
  93. package/src/__tests__/landing-hero.test.tsx +27 -0
  94. package/src/__tests__/landing-nav.test.tsx +24 -0
  95. package/src/__tests__/layout-snapshots.test.tsx +167 -0
  96. package/src/__tests__/logger.test.ts +54 -0
  97. package/src/__tests__/login-page-redirect.test.tsx +142 -0
  98. package/src/__tests__/manifest-validation.test.ts +126 -0
  99. package/src/__tests__/marketplace-admin.test.tsx +151 -0
  100. package/src/__tests__/marketplace.test.tsx +609 -0
  101. package/src/__tests__/merge-api-rates.test.ts +70 -0
  102. package/src/__tests__/middleware.test.ts +690 -0
  103. package/src/__tests__/network-page.test.tsx +100 -0
  104. package/src/__tests__/next-config-headers.test.ts +28 -0
  105. package/src/__tests__/not-found.test.tsx +26 -0
  106. package/src/__tests__/notifications.test.tsx +128 -0
  107. package/src/__tests__/oauth-buttons.test.tsx +101 -0
  108. package/src/__tests__/oauth-error-mapping.test.tsx +97 -0
  109. package/src/__tests__/observability.test.tsx +541 -0
  110. package/src/__tests__/onboarding-data.test.ts +363 -0
  111. package/src/__tests__/onboarding-page.test.tsx +113 -0
  112. package/src/__tests__/onboarding-store.test.ts +121 -0
  113. package/src/__tests__/org-billing-api.test.tsx +70 -0
  114. package/src/__tests__/org-billing-null-guards.test.ts +64 -0
  115. package/src/__tests__/org-billing-page.test.tsx +124 -0
  116. package/src/__tests__/plugin-definition.test.ts +43 -0
  117. package/src/__tests__/plugin-install-flow.test.tsx +535 -0
  118. package/src/__tests__/plugin-registry.test.tsx +475 -0
  119. package/src/__tests__/plugin-setup/setup-chat-panel.test.ts +142 -0
  120. package/src/__tests__/plugin-setup/use-plugin-setup-chat.test.ts +49 -0
  121. package/src/__tests__/plugin-tool-definitions.test.ts +51 -0
  122. package/src/__tests__/plugin-tool-sync.test.ts +59 -0
  123. package/src/__tests__/portfolio-chart.test.tsx +24 -0
  124. package/src/__tests__/pricing.test.tsx +107 -0
  125. package/src/__tests__/promotion-form.test.tsx +180 -0
  126. package/src/__tests__/promotions-list.test.tsx +194 -0
  127. package/src/__tests__/provider-key-api.test.ts +134 -0
  128. package/src/__tests__/resend-verification-button.test.tsx +104 -0
  129. package/src/__tests__/sanitize-redirect-url.test.ts +47 -0
  130. package/src/__tests__/secrets-audit-pagination.test.tsx +139 -0
  131. package/src/__tests__/settings.test.tsx +937 -0
  132. package/src/__tests__/setup-checklist.test.tsx +274 -0
  133. package/src/__tests__/setup.ts +82 -0
  134. package/src/__tests__/smoke.test.tsx +10 -0
  135. package/src/__tests__/snapshot-api.test.ts +104 -0
  136. package/src/__tests__/status-api.test.ts +46 -0
  137. package/src/__tests__/status-badge.test.tsx +33 -0
  138. package/src/__tests__/status-colors.test.ts +83 -0
  139. package/src/__tests__/status-page.test.tsx +86 -0
  140. package/src/__tests__/step-superpowers.test.tsx +218 -0
  141. package/src/__tests__/story-sections.test.tsx +24 -0
  142. package/src/__tests__/superpower-content-sanitize.test.tsx +87 -0
  143. package/src/__tests__/superpower-content.test.tsx +44 -0
  144. package/src/__tests__/suspension-banner.test.tsx +140 -0
  145. package/src/__tests__/tenant-context.test.tsx +146 -0
  146. package/src/__tests__/tenant-keys-api.test.ts +114 -0
  147. package/src/__tests__/tenant-table-pagination.test.tsx +124 -0
  148. package/src/__tests__/terminal-log-cleanup.test.tsx +51 -0
  149. package/src/__tests__/terminal-sequence.test.tsx +28 -0
  150. package/src/__tests__/transaction-history.test.tsx +325 -0
  151. package/src/__tests__/trpc-types.test.ts +102 -0
  152. package/src/__tests__/use-capability-meta.test.ts +161 -0
  153. package/src/__tests__/use-chat.test.ts +616 -0
  154. package/src/__tests__/use-has-org.test.ts +44 -0
  155. package/src/__tests__/use-image-status.test.ts +77 -0
  156. package/src/__tests__/use-pagination-params.test.ts +88 -0
  157. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +53 -0
  158. package/src/__tests__/use-webmcp.test.ts +119 -0
  159. package/src/__tests__/validate-elevenlabs-key.test.ts +95 -0
  160. package/src/__tests__/validate-redirect-url.test.ts +61 -0
  161. package/src/__tests__/verify-page.test.tsx +140 -0
  162. package/src/__tests__/verify-redirect.test.tsx +41 -0
  163. package/src/__tests__/verify-result-banner.test.tsx +66 -0
  164. package/src/__tests__/webmcp-feature-detect.test.ts +54 -0
  165. package/src/__tests__/webmcp-hook.test.tsx +72 -0
  166. package/src/__tests__/webmcp-marketplace-onboarding-tools.test.ts +185 -0
  167. package/src/__tests__/webmcp-register.test.ts +103 -0
  168. package/src/__tests__/webmcp-set-provider.test.ts +47 -0
  169. package/src/__tests__/webmcp-tools.test.ts +348 -0
  170. package/src/app/(auth)/error.tsx +72 -0
  171. package/src/app/(auth)/forgot-password/page.tsx +137 -0
  172. package/src/app/(auth)/layout.tsx +14 -0
  173. package/src/app/(auth)/loading.tsx +26 -0
  174. package/src/app/(auth)/login/page.tsx +188 -0
  175. package/src/app/(auth)/reset-password/page.tsx +169 -0
  176. package/src/app/(auth)/signup/page.tsx +309 -0
  177. package/src/app/(dashboard)/billing/credits/page.tsx +209 -0
  178. package/src/app/(dashboard)/billing/error.tsx +72 -0
  179. package/src/app/(dashboard)/billing/layout.tsx +73 -0
  180. package/src/app/(dashboard)/billing/loading.tsx +41 -0
  181. package/src/app/(dashboard)/billing/payment/page.tsx +639 -0
  182. package/src/app/(dashboard)/billing/plans/page.tsx +58 -0
  183. package/src/app/(dashboard)/billing/referrals/page.tsx +7 -0
  184. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +348 -0
  185. package/src/app/(dashboard)/billing/usage/page.tsx +663 -0
  186. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +400 -0
  187. package/src/app/(dashboard)/changesets/[id]/error.tsx +57 -0
  188. package/src/app/(dashboard)/changesets/[id]/loading.tsx +23 -0
  189. package/src/app/(dashboard)/changesets/[id]/page.tsx +10 -0
  190. package/src/app/(dashboard)/changesets/error.tsx +72 -0
  191. package/src/app/(dashboard)/changesets/page.tsx +10 -0
  192. package/src/app/(dashboard)/chat/page.tsx +74 -0
  193. package/src/app/(dashboard)/dashboard/bots/[id]/settings/page.tsx +10 -0
  194. package/src/app/(dashboard)/dashboard/network/page.tsx +97 -0
  195. package/src/app/(dashboard)/dashboard/page.tsx +13 -0
  196. package/src/app/(dashboard)/error.tsx +72 -0
  197. package/src/app/(dashboard)/layout.tsx +113 -0
  198. package/src/app/(dashboard)/loading.tsx +27 -0
  199. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +548 -0
  200. package/src/app/(dashboard)/marketplace/error.tsx +72 -0
  201. package/src/app/(dashboard)/marketplace/loading.tsx +27 -0
  202. package/src/app/(dashboard)/marketplace/page.tsx +268 -0
  203. package/src/app/(dashboard)/not-found.tsx +46 -0
  204. package/src/app/(dashboard)/onboarding/page.tsx +267 -0
  205. package/src/app/(dashboard)/settings/account/page.tsx +132 -0
  206. package/src/app/(dashboard)/settings/activity/page.tsx +280 -0
  207. package/src/app/(dashboard)/settings/api-keys/page.tsx +530 -0
  208. package/src/app/(dashboard)/settings/brain/page.tsx +412 -0
  209. package/src/app/(dashboard)/settings/error.tsx +72 -0
  210. package/src/app/(dashboard)/settings/layout.tsx +114 -0
  211. package/src/app/(dashboard)/settings/loading.tsx +31 -0
  212. package/src/app/(dashboard)/settings/notifications/page.tsx +216 -0
  213. package/src/app/(dashboard)/settings/org/page.tsx +617 -0
  214. package/src/app/(dashboard)/settings/profile/page.tsx +510 -0
  215. package/src/app/(dashboard)/settings/providers/page.tsx +842 -0
  216. package/src/app/(dashboard)/settings/secrets/page.tsx +658 -0
  217. package/src/app/(dashboard)/settings/security/page.tsx +1133 -0
  218. package/src/app/admin/accounting/loading.tsx +32 -0
  219. package/src/app/admin/accounting/page.tsx +5 -0
  220. package/src/app/admin/affiliates/loading.tsx +32 -0
  221. package/src/app/admin/affiliates/page.tsx +5 -0
  222. package/src/app/admin/audit/loading.tsx +32 -0
  223. package/src/app/admin/audit/page.tsx +5 -0
  224. package/src/app/admin/billing-health/loading.tsx +17 -0
  225. package/src/app/admin/billing-health/page.tsx +10 -0
  226. package/src/app/admin/compliance/page.tsx +5 -0
  227. package/src/app/admin/error.tsx +72 -0
  228. package/src/app/admin/gpu/loading.tsx +38 -0
  229. package/src/app/admin/gpu/page.tsx +5 -0
  230. package/src/app/admin/incidents/page.tsx +10 -0
  231. package/src/app/admin/inference/loading.tsx +32 -0
  232. package/src/app/admin/inference/page.tsx +5 -0
  233. package/src/app/admin/layout.tsx +44 -0
  234. package/src/app/admin/loading.tsx +32 -0
  235. package/src/app/admin/marketplace/loading.tsx +32 -0
  236. package/src/app/admin/marketplace/page.tsx +5 -0
  237. package/src/app/admin/migrations/loading.tsx +22 -0
  238. package/src/app/admin/migrations/page.tsx +5 -0
  239. package/src/app/admin/onboarding/loading.tsx +18 -0
  240. package/src/app/admin/onboarding/page.tsx +5 -0
  241. package/src/app/admin/promotions/[id]/edit/loading.tsx +16 -0
  242. package/src/app/admin/promotions/[id]/edit/page.tsx +56 -0
  243. package/src/app/admin/promotions/[id]/loading.tsx +15 -0
  244. package/src/app/admin/promotions/[id]/page.tsx +311 -0
  245. package/src/app/admin/promotions/loading.tsx +21 -0
  246. package/src/app/admin/promotions/new/loading.tsx +16 -0
  247. package/src/app/admin/promotions/new/page.tsx +12 -0
  248. package/src/app/admin/promotions/page.tsx +266 -0
  249. package/src/app/admin/rate-overrides/loading.tsx +17 -0
  250. package/src/app/admin/rate-overrides/page.tsx +290 -0
  251. package/src/app/admin/roles/loading.tsx +27 -0
  252. package/src/app/admin/roles/page.tsx +5 -0
  253. package/src/app/admin/tenants/loading.tsx +32 -0
  254. package/src/app/admin/tenants/page.tsx +5 -0
  255. package/src/app/apple-icon.tsx +32 -0
  256. package/src/app/auth/callback/[provider]/page.tsx +104 -0
  257. package/src/app/auth/verify/page.tsx +224 -0
  258. package/src/app/channels/error.tsx +72 -0
  259. package/src/app/channels/loading.tsx +29 -0
  260. package/src/app/channels/page.tsx +262 -0
  261. package/src/app/channels/setup/[plugin]/page.tsx +136 -0
  262. package/src/app/error.tsx +72 -0
  263. package/src/app/favicon.ico +0 -0
  264. package/src/app/fleet/error.tsx +72 -0
  265. package/src/app/fleet/health/page.tsx +9 -0
  266. package/src/app/fleet/layout.tsx +14 -0
  267. package/src/app/fleet/loading.tsx +33 -0
  268. package/src/app/fleet/page.tsx +5 -0
  269. package/src/app/global-error.tsx +96 -0
  270. package/src/app/globals.css +251 -0
  271. package/src/app/icon.svg +4 -0
  272. package/src/app/instances/[id]/instance-detail-client.tsx +1298 -0
  273. package/src/app/instances/[id]/page.tsx +10 -0
  274. package/src/app/instances/error.tsx +72 -0
  275. package/src/app/instances/instance-list-client.tsx +540 -0
  276. package/src/app/instances/loading.tsx +33 -0
  277. package/src/app/instances/new/create-instance-client.tsx +377 -0
  278. package/src/app/instances/new/page.tsx +9 -0
  279. package/src/app/instances/page.tsx +9 -0
  280. package/src/app/layout.tsx +83 -0
  281. package/src/app/not-found.tsx +38 -0
  282. package/src/app/og/route.tsx +50 -0
  283. package/src/app/page.tsx +39 -0
  284. package/src/app/plugins/error.tsx +72 -0
  285. package/src/app/plugins/layout.tsx +14 -0
  286. package/src/app/plugins/loading.tsx +30 -0
  287. package/src/app/plugins/page.tsx +555 -0
  288. package/src/app/pricing/error.tsx +72 -0
  289. package/src/app/pricing/loading.tsx +25 -0
  290. package/src/app/pricing/page.tsx +20 -0
  291. package/src/app/privacy/page.tsx +406 -0
  292. package/src/app/robots.ts +9 -0
  293. package/src/app/sitemap.ts +11 -0
  294. package/src/app/status/error.tsx +72 -0
  295. package/src/app/status/loading.tsx +21 -0
  296. package/src/app/status/page.tsx +20 -0
  297. package/src/app/terms/page.tsx +414 -0
  298. package/src/components/account-switcher.tsx +82 -0
  299. package/src/components/admin/accounting-dashboard.tsx +190 -0
  300. package/src/components/admin/admin-guard.tsx +36 -0
  301. package/src/components/admin/admin-nav.tsx +71 -0
  302. package/src/components/admin/affiliate-dashboard.tsx +564 -0
  303. package/src/components/admin/audit-log-table.tsx +336 -0
  304. package/src/components/admin/billing-health-dashboard.test.tsx +40 -0
  305. package/src/components/admin/billing-health-dashboard.tsx +416 -0
  306. package/src/components/admin/bulk-actions-bar.test.tsx +92 -0
  307. package/src/components/admin/bulk-actions-bar.tsx +80 -0
  308. package/src/components/admin/bulk-export-dialog.test.tsx +75 -0
  309. package/src/components/admin/bulk-export-dialog.tsx +189 -0
  310. package/src/components/admin/bulk-grant-dialog.test.tsx +81 -0
  311. package/src/components/admin/bulk-grant-dialog.tsx +147 -0
  312. package/src/components/admin/bulk-preview-dialog.test.tsx +72 -0
  313. package/src/components/admin/bulk-preview-dialog.tsx +106 -0
  314. package/src/components/admin/bulk-reactivate-dialog.test.tsx +51 -0
  315. package/src/components/admin/bulk-reactivate-dialog.tsx +55 -0
  316. package/src/components/admin/bulk-select-all-banner.test.tsx +36 -0
  317. package/src/components/admin/bulk-select-all-banner.tsx +44 -0
  318. package/src/components/admin/bulk-suspend-dialog.test.tsx +77 -0
  319. package/src/components/admin/bulk-suspend-dialog.tsx +129 -0
  320. package/src/components/admin/bulk-undo-toast.test.tsx +66 -0
  321. package/src/components/admin/bulk-undo-toast.tsx +121 -0
  322. package/src/components/admin/compliance-dashboard.tsx +1341 -0
  323. package/src/components/admin/gpu-dashboard.tsx +552 -0
  324. package/src/components/admin/grant-credits-dialog.tsx +121 -0
  325. package/src/components/admin/incident-dashboard.test.tsx +44 -0
  326. package/src/components/admin/incident-dashboard.tsx +717 -0
  327. package/src/components/admin/inference-dashboard.tsx +415 -0
  328. package/src/components/admin/marketplace-admin.tsx +765 -0
  329. package/src/components/admin/migrations-dashboard.tsx +404 -0
  330. package/src/components/admin/onboarding-dashboard.tsx +422 -0
  331. package/src/components/admin/promotions/promotion-form.tsx +440 -0
  332. package/src/components/admin/roles-dashboard.tsx +278 -0
  333. package/src/components/admin/suspend-dialog.tsx +98 -0
  334. package/src/components/admin/tenant-notes-panel.tsx +134 -0
  335. package/src/components/admin/tenant-row-actions.tsx +78 -0
  336. package/src/components/admin/tenant-table.tsx +339 -0
  337. package/src/components/auth/auth-error.tsx +22 -0
  338. package/src/components/auth/auth-redirect.tsx +18 -0
  339. package/src/components/auth/auth-shell.tsx +25 -0
  340. package/src/components/auth/email-verification-banner.tsx +25 -0
  341. package/src/components/auth/email-verification-result-banner.tsx +70 -0
  342. package/src/components/auth/resend-verification-button.tsx +94 -0
  343. package/src/components/auth/wopr-wordmark.tsx +19 -0
  344. package/src/components/billing/add-payment-method-dialog.tsx +267 -0
  345. package/src/components/billing/affiliate-dashboard.tsx +300 -0
  346. package/src/components/billing/auto-topup-card.tsx +432 -0
  347. package/src/components/billing/buy-credits-panel.tsx +180 -0
  348. package/src/components/billing/buy-crypto-credits-panel.tsx +96 -0
  349. package/src/components/billing/byok-callout.tsx +87 -0
  350. package/src/components/billing/coupon-input.tsx +86 -0
  351. package/src/components/billing/credit-balance.tsx +79 -0
  352. package/src/components/billing/degraded-state-banner.tsx +95 -0
  353. package/src/components/billing/dividend-banner.tsx +97 -0
  354. package/src/components/billing/dividend-eligibility.tsx +86 -0
  355. package/src/components/billing/dividend-pool-stats.tsx +86 -0
  356. package/src/components/billing/first-dividend-dialog.tsx +109 -0
  357. package/src/components/billing/low-balance-banner.tsx +50 -0
  358. package/src/components/billing/org-billing-page.tsx +360 -0
  359. package/src/components/billing/suspension-banner.tsx +53 -0
  360. package/src/components/billing/transaction-history.tsx +239 -0
  361. package/src/components/bot-settings/__tests__/bot-settings-client.test.tsx +205 -0
  362. package/src/components/bot-settings/backups-tab.tsx +377 -0
  363. package/src/components/bot-settings/bot-settings-client.tsx +1712 -0
  364. package/src/components/bot-settings/resources-tab.tsx +203 -0
  365. package/src/components/bot-settings/storage-tab.tsx +248 -0
  366. package/src/components/bot-settings/vps-info-panel.tsx +132 -0
  367. package/src/components/bot-settings/vps-upgrade-card.tsx +110 -0
  368. package/src/components/capability/CapabilityResolver.tsx +113 -0
  369. package/src/components/channel-wizard/field-interactive.tsx +48 -0
  370. package/src/components/channel-wizard/field-oauth.tsx +181 -0
  371. package/src/components/channel-wizard/field-paste.tsx +47 -0
  372. package/src/components/channel-wizard/field-qr.tsx +302 -0
  373. package/src/components/channel-wizard/index.ts +6 -0
  374. package/src/components/channel-wizard/step-renderer.tsx +103 -0
  375. package/src/components/channel-wizard/wizard.tsx +200 -0
  376. package/src/components/chat/ambient-dot.tsx +32 -0
  377. package/src/components/chat/chat-input.tsx +56 -0
  378. package/src/components/chat/chat-message.tsx +36 -0
  379. package/src/components/chat/chat-panel.tsx +138 -0
  380. package/src/components/chat/chat-widget.tsx +41 -0
  381. package/src/components/chat/index.ts +5 -0
  382. package/src/components/dashboard/command-center.tsx +614 -0
  383. package/src/components/instances/friends-tab.test.tsx +265 -0
  384. package/src/components/instances/friends-tab.tsx +721 -0
  385. package/src/components/landing/hero.tsx +53 -0
  386. package/src/components/landing/landing-nav.tsx +21 -0
  387. package/src/components/landing/landing-page.tsx +71 -0
  388. package/src/components/landing/portfolio-chart.tsx +349 -0
  389. package/src/components/landing/story-sections.tsx +50 -0
  390. package/src/components/landing/terminal-lines.ts +99 -0
  391. package/src/components/landing/terminal-sequence.tsx +453 -0
  392. package/src/components/landing/typing-effect.tsx +43 -0
  393. package/src/components/marketplace/category-filter.tsx +61 -0
  394. package/src/components/marketplace/empty-state.tsx +61 -0
  395. package/src/components/marketplace/featured-heroes.tsx +84 -0
  396. package/src/components/marketplace/first-visit-hero.tsx +110 -0
  397. package/src/components/marketplace/index.ts +9 -0
  398. package/src/components/marketplace/install-wizard.tsx +782 -0
  399. package/src/components/marketplace/marketplace-tabs.tsx +54 -0
  400. package/src/components/marketplace/plugin-card.tsx +129 -0
  401. package/src/components/marketplace/superpower-card.tsx +104 -0
  402. package/src/components/marketplace/superpower-content.tsx +117 -0
  403. package/src/components/marketplace/terminal-search.tsx +67 -0
  404. package/src/components/oauth-buttons.tsx +75 -0
  405. package/src/components/observability/fleet-health.tsx +370 -0
  406. package/src/components/observability/health-overview.tsx +246 -0
  407. package/src/components/observability/logs-viewer.tsx +215 -0
  408. package/src/components/observability/metrics-dashboard.tsx +288 -0
  409. package/src/components/onboarding/fallback-setup.tsx +137 -0
  410. package/src/components/onboarding/index.ts +3 -0
  411. package/src/components/onboarding/setup-checklist.tsx +333 -0
  412. package/src/components/onboarding/step-superpowers.tsx +122 -0
  413. package/src/components/plugin-setup/index.ts +1 -0
  414. package/src/components/plugin-setup/setup-chat-panel.tsx +188 -0
  415. package/src/components/pricing/dividend-calculator.tsx +47 -0
  416. package/src/components/pricing/dividend-stats.tsx +117 -0
  417. package/src/components/pricing/pricing-page.tsx +229 -0
  418. package/src/components/settings/create-org-wizard.tsx +225 -0
  419. package/src/components/sidebar.tsx +202 -0
  420. package/src/components/status/status-page.tsx +209 -0
  421. package/src/components/status-badge.tsx +28 -0
  422. package/src/components/theme-provider.tsx +8 -0
  423. package/src/components/ui/alert-dialog.tsx +141 -0
  424. package/src/components/ui/badge.tsx +47 -0
  425. package/src/components/ui/banner.tsx +36 -0
  426. package/src/components/ui/button.tsx +64 -0
  427. package/src/components/ui/card.tsx +75 -0
  428. package/src/components/ui/checkbox.tsx +52 -0
  429. package/src/components/ui/collapsible.tsx +31 -0
  430. package/src/components/ui/credit-detailed.tsx +33 -0
  431. package/src/components/ui/dialog.tsx +143 -0
  432. package/src/components/ui/dropdown-menu.tsx +228 -0
  433. package/src/components/ui/form.tsx +151 -0
  434. package/src/components/ui/input.tsx +21 -0
  435. package/src/components/ui/label.tsx +21 -0
  436. package/src/components/ui/popover.tsx +74 -0
  437. package/src/components/ui/progress.tsx +28 -0
  438. package/src/components/ui/radio-group.tsx +45 -0
  439. package/src/components/ui/select.tsx +175 -0
  440. package/src/components/ui/separator.tsx +28 -0
  441. package/src/components/ui/sheet.tsx +125 -0
  442. package/src/components/ui/skeleton.tsx +15 -0
  443. package/src/components/ui/switch.tsx +35 -0
  444. package/src/components/ui/table.tsx +92 -0
  445. package/src/components/ui/tabs.tsx +81 -0
  446. package/src/components/ui/textarea.tsx +18 -0
  447. package/src/components/ui/tooltip.tsx +44 -0
  448. package/src/config/provider-docs.ts +17 -0
  449. package/src/hooks/__tests__/use-async.test.ts +127 -0
  450. package/src/hooks/__tests__/use-count-up.test.ts +129 -0
  451. package/src/hooks/__tests__/use-debounce.test.ts +105 -0
  452. package/src/hooks/__tests__/use-fleet-sse.test.ts +216 -0
  453. package/src/hooks/__tests__/use-local-storage.test.ts +74 -0
  454. package/src/hooks/__tests__/use-mobile.test.ts +86 -0
  455. package/src/hooks/__tests__/use-save-queue.test.ts +159 -0
  456. package/src/hooks/use-async.ts +54 -0
  457. package/src/hooks/use-capability-meta.ts +99 -0
  458. package/src/hooks/use-count-up.ts +23 -0
  459. package/src/hooks/use-debounce.ts +12 -0
  460. package/src/hooks/use-fleet-sse.ts +47 -0
  461. package/src/hooks/use-has-org.ts +18 -0
  462. package/src/hooks/use-image-status.ts +36 -0
  463. package/src/hooks/use-local-storage.ts +36 -0
  464. package/src/hooks/use-mobile.ts +17 -0
  465. package/src/hooks/use-page-context.ts +24 -0
  466. package/src/hooks/use-pagination-params.ts +30 -0
  467. package/src/hooks/use-plugin-registry.ts +247 -0
  468. package/src/hooks/use-plugin-setup-chat.ts +211 -0
  469. package/src/hooks/use-save-queue.ts +54 -0
  470. package/src/hooks/use-webmcp.ts +40 -0
  471. package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +112 -0
  472. package/src/lib/__tests__/admin-api.test.ts +487 -0
  473. package/src/lib/__tests__/api-bot-crud.test.ts +391 -0
  474. package/src/lib/__tests__/api-fetch.test.ts +196 -0
  475. package/src/lib/__tests__/bot-settings-data.test.ts +352 -0
  476. package/src/lib/__tests__/org-api.test.ts +281 -0
  477. package/src/lib/__tests__/org-billing-api.test.ts +242 -0
  478. package/src/lib/__tests__/pricing-data.test.ts +32 -0
  479. package/src/lib/__tests__/settings-api.test.ts +272 -0
  480. package/src/lib/admin-affiliate-api.ts +51 -0
  481. package/src/lib/admin-api.ts +325 -0
  482. package/src/lib/admin-compliance-api.ts +127 -0
  483. package/src/lib/admin-gpu-api.ts +82 -0
  484. package/src/lib/admin-incident-api.ts +121 -0
  485. package/src/lib/admin-inference-api.ts +47 -0
  486. package/src/lib/admin-marketplace-api.ts +97 -0
  487. package/src/lib/api-config.test.ts +111 -0
  488. package/src/lib/api-config.ts +65 -0
  489. package/src/lib/api-errors.test.ts +43 -0
  490. package/src/lib/api.ts +2011 -0
  491. package/src/lib/auth-client.ts +11 -0
  492. package/src/lib/bot-settings-data.ts +342 -0
  493. package/src/lib/brand-config.ts +145 -0
  494. package/src/lib/brand.ts +669 -0
  495. package/src/lib/changeset-api.ts +29 -0
  496. package/src/lib/changeset-types.ts +56 -0
  497. package/src/lib/channel-manifests.ts +50 -0
  498. package/src/lib/chat/chat-context.tsx +70 -0
  499. package/src/lib/chat/chat-store.ts +62 -0
  500. package/src/lib/chat/types.ts +35 -0
  501. package/src/lib/chat/use-chat.ts +255 -0
  502. package/src/lib/cost-comparison-data.test.ts +95 -0
  503. package/src/lib/cost-comparison-data.ts +54 -0
  504. package/src/lib/errors.test.ts +64 -0
  505. package/src/lib/errors.ts +52 -0
  506. package/src/lib/fetch-utils.test.ts +57 -0
  507. package/src/lib/fetch-utils.ts +25 -0
  508. package/src/lib/format-credit.test.ts +66 -0
  509. package/src/lib/format-credit.ts +24 -0
  510. package/src/lib/format.test.ts +62 -0
  511. package/src/lib/format.ts +17 -0
  512. package/src/lib/logger.ts +28 -0
  513. package/src/lib/marketplace-data.ts +346 -0
  514. package/src/lib/oauth-errors.ts +19 -0
  515. package/src/lib/onboarding-data.ts +1265 -0
  516. package/src/lib/onboarding-store.ts +233 -0
  517. package/src/lib/org-api.ts +74 -0
  518. package/src/lib/org-billing-api.ts +81 -0
  519. package/src/lib/page-prompts.test.ts +32 -0
  520. package/src/lib/page-prompts.ts +23 -0
  521. package/src/lib/plugin/index.ts +32 -0
  522. package/src/lib/plugin/tool-definitions.ts +306 -0
  523. package/src/lib/pricing-data.ts +115 -0
  524. package/src/lib/promotions-types.ts +58 -0
  525. package/src/lib/settings-api.ts +63 -0
  526. package/src/lib/status-colors.ts +38 -0
  527. package/src/lib/tenant-context.tsx +134 -0
  528. package/src/lib/trpc-types.ts +173 -0
  529. package/src/lib/trpc.tsx +86 -0
  530. package/src/lib/utils.test.ts +55 -0
  531. package/src/lib/utils.ts +18 -0
  532. package/src/lib/validate-redirect-url.ts +39 -0
  533. package/src/lib/webmcp/feature-detect.ts +13 -0
  534. package/src/lib/webmcp/marketplace-onboarding-tools.ts +202 -0
  535. package/src/lib/webmcp/register.ts +44 -0
  536. package/src/lib/webmcp/tools.ts +422 -0
  537. package/src/proxy.ts +258 -0
  538. package/src/types/missing-deps.d.ts +160 -0
  539. package/src/types/motion-dom.d.ts +162 -0
  540. package/src/types/vitest-matchers.d.ts +40 -0
  541. package/src/types/web-mcp.d.ts +22 -0
  542. package/tsconfig.json +34 -0
  543. package/vitest.config.ts +26 -0
@@ -0,0 +1,25 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function PricingLoading() {
4
+ return (
5
+ <div className="space-y-6 p-6">
6
+ <div className="space-y-2">
7
+ <Skeleton className="h-8 w-48" />
8
+ <Skeleton className="h-4 w-64" />
9
+ </div>
10
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
11
+ {Array.from({ length: 3 }, (_, n) => `sk-${n}`).map((skId) => (
12
+ <div key={skId} className="rounded-sm border p-6 space-y-4">
13
+ <Skeleton className="h-5 w-24" />
14
+ <Skeleton className="h-10 w-20" />
15
+ <Skeleton className="h-4 w-32" />
16
+ {Array.from({ length: 4 }, (_, n) => `feat-${n}`).map((featId) => (
17
+ <Skeleton key={featId} className="h-3 w-full" />
18
+ ))}
19
+ <Skeleton className="h-10 w-full" />
20
+ </div>
21
+ ))}
22
+ </div>
23
+ </div>
24
+ );
25
+ }
@@ -0,0 +1,20 @@
1
+ import type { Metadata } from "next";
2
+ import { PricingPage } from "@/components/pricing/pricing-page";
3
+ import { SITE_URL } from "@/lib/api-config";
4
+ import { getBrandConfig } from "@/lib/brand-config";
5
+
6
+ const brand = getBrandConfig();
7
+
8
+ export const metadata: Metadata = {
9
+ title: `Pricing — ${brand.brandName} pays for itself`,
10
+ description: `Every day, ${brand.brandName} distributes credits back to active users. The bigger the community grows, the more you receive. Early users get the most.`,
11
+ openGraph: {
12
+ title: `Pricing — ${brand.brandName} pays for itself`,
13
+ description: `Every day, ${brand.brandName} distributes credits back to active users. The bigger the community grows, the more you receive.`,
14
+ url: `${SITE_URL}/pricing`,
15
+ },
16
+ };
17
+
18
+ export default async function Page() {
19
+ return <PricingPage />;
20
+ }
@@ -0,0 +1,406 @@
1
+ import type { Metadata } from "next";
2
+ import Link from "next/link";
3
+ import { LandingNav } from "@/components/landing/landing-nav";
4
+ import { getBrandConfig } from "@/lib/brand-config";
5
+
6
+ const brand = getBrandConfig();
7
+
8
+ export const metadata: Metadata = {
9
+ title: `Privacy Policy — ${brand.productName}`,
10
+ description: `Privacy Policy for ${brand.productName}`,
11
+ };
12
+
13
+ export default function PrivacyPage() {
14
+ return (
15
+ <>
16
+ <LandingNav />
17
+ <div className="mx-auto max-w-2xl px-6 py-16">
18
+ <h1 className="text-2xl font-bold tracking-tight">Privacy Policy</h1>
19
+ <p className="mt-2 text-sm text-muted-foreground">Last updated: February 2026</p>
20
+
21
+ <nav className="mt-6 rounded-sm border border-border bg-card p-4">
22
+ <p className="mb-3 text-xs font-medium uppercase tracking-[0.15em] text-muted-foreground">
23
+ Contents
24
+ </p>
25
+ <ol className="list-none space-y-1.5 text-sm text-muted-foreground">
26
+ <li>
27
+ <a href="#section-1" className="underline underline-offset-4 hover:text-foreground">
28
+ 1. Identity and Contact Details
29
+ </a>
30
+ </li>
31
+ <li>
32
+ <a href="#section-2" className="underline underline-offset-4 hover:text-foreground">
33
+ 2. What We Collect and Why
34
+ </a>
35
+ </li>
36
+ <li>
37
+ <a href="#section-3" className="underline underline-offset-4 hover:text-foreground">
38
+ 3. When We Access or Share Your Information
39
+ </a>
40
+ </li>
41
+ <li>
42
+ <a href="#section-4" className="underline underline-offset-4 hover:text-foreground">
43
+ 4. Your Rights Under GDPR
44
+ </a>
45
+ </li>
46
+ <li>
47
+ <a href="#section-5" className="underline underline-offset-4 hover:text-foreground">
48
+ 5. Your Rights Under CCPA
49
+ </a>
50
+ </li>
51
+ <li>
52
+ <a href="#section-6" className="underline underline-offset-4 hover:text-foreground">
53
+ 6. Data Retention
54
+ </a>
55
+ </li>
56
+ <li>
57
+ <a href="#section-7" className="underline underline-offset-4 hover:text-foreground">
58
+ 7. Cookies and Tracking
59
+ </a>
60
+ </li>
61
+ <li>
62
+ <a href="#section-8" className="underline underline-offset-4 hover:text-foreground">
63
+ 8. Security
64
+ </a>
65
+ </li>
66
+ <li>
67
+ <a href="#section-9" className="underline underline-offset-4 hover:text-foreground">
68
+ 9. International Data Transfers
69
+ </a>
70
+ </li>
71
+ <li>
72
+ <a href="#section-10" className="underline underline-offset-4 hover:text-foreground">
73
+ 10. Data Breach Notification
74
+ </a>
75
+ </li>
76
+ <li>
77
+ <a href="#section-11" className="underline underline-offset-4 hover:text-foreground">
78
+ 11. Children&apos;s Privacy
79
+ </a>
80
+ </li>
81
+ <li>
82
+ <a href="#section-12" className="underline underline-offset-4 hover:text-foreground">
83
+ 12. Changes to This Policy
84
+ </a>
85
+ </li>
86
+ <li>
87
+ <a href="#section-13" className="underline underline-offset-4 hover:text-foreground">
88
+ 13. Contact
89
+ </a>
90
+ </li>
91
+ </ol>
92
+ </nav>
93
+
94
+ <div className="mt-8 space-y-8 text-sm leading-relaxed text-muted-foreground">
95
+ <section id="section-1" className="scroll-mt-16">
96
+ <h2 className="mb-2 text-base font-semibold text-foreground">
97
+ 1. Identity and Contact Details
98
+ </h2>
99
+ <p>
100
+ {brand.companyLegalName} (&ldquo;{brand.brandName},&rdquo; &ldquo;we,&rdquo;
101
+ &ldquo;us,&rdquo; or &ldquo;our&rdquo;) is the data controller responsible for your
102
+ personal data. We operate the {brand.productName} platform available at {brand.domain}
103
+ .
104
+ </p>
105
+ <p className="mt-2">
106
+ If you have questions about how we handle your data, or if you wish to exercise any of
107
+ your rights described below, contact us at{" "}
108
+ <a
109
+ href={`mailto:${brand.emails.privacy}`}
110
+ className="text-foreground underline underline-offset-4"
111
+ >
112
+ {brand.emails.privacy}
113
+ </a>
114
+ .
115
+ </p>
116
+ </section>
117
+
118
+ <section id="section-2" className="scroll-mt-16">
119
+ <h2 className="mb-2 text-base font-semibold text-foreground">
120
+ 2. What We Collect and Why
121
+ </h2>
122
+ <p>
123
+ We only collect information that is necessary to provide and improve{" "}
124
+ {brand.productName}
125
+ services. We do not collect data for advertising or sell your information to third
126
+ parties.
127
+ </p>
128
+
129
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">Account information</h3>
130
+ <p>
131
+ Your name and email address, collected when you create an account. We use this to
132
+ identify you, communicate with you about your account, and send transactional emails
133
+ such as password resets and billing notifications. Legal basis: performance of our
134
+ contract with you.
135
+ </p>
136
+
137
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">Billing information</h3>
138
+ <p>
139
+ Payment card details are processed directly by Stripe and are never stored on{" "}
140
+ {brand.brandName}
141
+ servers. We receive only a tokenized reference, your billing email, and transaction
142
+ history from Stripe. Legal basis: performance of our contract with you.
143
+ </p>
144
+
145
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">API keys</h3>
146
+ <p>
147
+ You provide your own API keys for third-party AI providers (the &ldquo;bring your own
148
+ key&rdquo; model). These keys are encrypted at rest and used only to make requests to
149
+ your chosen providers on your behalf. We do not log or store the content of AI
150
+ interactions. Legal basis: performance of our contract with you.
151
+ </p>
152
+
153
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">Bot configuration</h3>
154
+ <p>
155
+ Plugin selections, channel configurations, provider settings, and other choices you
156
+ make while setting up and operating your bots. This data is necessary to deliver the
157
+ service as you have configured it. Legal basis: performance of our contract with you.
158
+ </p>
159
+
160
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">Usage data</h3>
161
+ <p>
162
+ API call counts, feature usage metrics, and hosted capability credit consumption. We
163
+ use this data for billing, capacity planning, and service improvement. Legal basis:
164
+ legitimate interest in maintaining and improving our service.
165
+ </p>
166
+
167
+ <h3 className="mb-1 mt-4 text-sm font-semibold text-foreground">Technical data</h3>
168
+ <p>
169
+ IP address, browser type, and operating system collected via web server logs. We use
170
+ this for security monitoring, abuse prevention, and debugging. Server logs are
171
+ retained for 90 days. Legal basis: legitimate interest in securing our service.
172
+ </p>
173
+ </section>
174
+
175
+ <section id="section-3" className="scroll-mt-16">
176
+ <h2 className="mb-2 text-base font-semibold text-foreground">
177
+ 3. When We Access or Share Your Information
178
+ </h2>
179
+ <p>
180
+ We do not sell your personal data. We do not use third-party tracking or advertising
181
+ cookies. We share data with the following categories of sub-processors only as needed
182
+ to provide the service:
183
+ </p>
184
+ <ul className="ml-4 mt-2 list-disc space-y-1">
185
+ <li>
186
+ <span className="text-foreground">Stripe</span> &mdash; payment processing. Stripe
187
+ receives your billing information to process subscription payments. Stripe&apos;s
188
+ privacy policy governs their handling of your payment data.
189
+ </li>
190
+ <li>
191
+ <span className="text-foreground">AI providers</span> (user-selected,
192
+ bring-your-own-key model) &mdash; request fulfillment. Your prompts and inputs are
193
+ sent to the AI provider you have configured. We do not choose or control which
194
+ provider you use.
195
+ </li>
196
+ <li>
197
+ <span className="text-foreground">Hosting provider</span> &mdash; infrastructure.
198
+ Our servers and Docker fleet are hosted by third-party infrastructure providers who
199
+ may process data on our behalf under strict data processing agreements.
200
+ </li>
201
+ <li>
202
+ <span className="text-foreground">Email service</span> &mdash; transactional emails.
203
+ We use a third-party email service to send password resets, billing notifications,
204
+ and other operational messages.
205
+ </li>
206
+ </ul>
207
+ <p className="mt-2">
208
+ We may also disclose information if required by law, to enforce our Terms of Service,
209
+ or to protect the rights, property, or safety of {brand.companyLegalName}, our users,
210
+ or the public.
211
+ </p>
212
+ </section>
213
+
214
+ <section id="section-4" className="scroll-mt-16">
215
+ <h2 className="mb-2 text-base font-semibold text-foreground">
216
+ 4. Your Rights Under GDPR
217
+ </h2>
218
+ <p>
219
+ If you are located in the European Union or European Economic Area, you have the
220
+ following rights under the General Data Protection Regulation:
221
+ </p>
222
+ <ul className="ml-4 mt-2 list-disc space-y-1">
223
+ <li>Right of access (Art. 15) &mdash; request a copy of your personal data</li>
224
+ <li>
225
+ Right to rectification (Art. 16) &mdash; correct inaccurate or incomplete data
226
+ </li>
227
+ <li>
228
+ Right to erasure (Art. 17) &mdash; request deletion of your personal data
229
+ (&ldquo;right to be forgotten&rdquo;)
230
+ </li>
231
+ <li>
232
+ Right to restrict processing (Art. 18) &mdash; limit how we use your data in certain
233
+ circumstances
234
+ </li>
235
+ <li>
236
+ Right to data portability (Art. 20) &mdash; receive your data in a structured,
237
+ commonly used, machine-readable format
238
+ </li>
239
+ <li>
240
+ Right to object (Art. 21) &mdash; object to processing based on legitimate interest
241
+ </li>
242
+ <li>Right to lodge a complaint with a supervisory authority in your member state</li>
243
+ </ul>
244
+ <p className="mt-2">
245
+ To exercise any of these rights, email{" "}
246
+ <a
247
+ href={`mailto:${brand.emails.privacy}`}
248
+ className="text-foreground underline underline-offset-4"
249
+ >
250
+ {brand.emails.privacy}
251
+ </a>
252
+ . We will respond within 30 days.
253
+ </p>
254
+ </section>
255
+
256
+ <section id="section-5" className="scroll-mt-16">
257
+ <h2 className="mb-2 text-base font-semibold text-foreground">
258
+ 5. Your Rights Under CCPA
259
+ </h2>
260
+ <p>
261
+ If you are a California resident, the California Consumer Privacy Act provides you
262
+ with the following rights:
263
+ </p>
264
+ <ul className="ml-4 mt-2 list-disc space-y-1">
265
+ <li>Right to know what personal information is collected, used, shared, or sold</li>
266
+ <li>Right to delete personal information held by us</li>
267
+ <li>
268
+ Right to opt-out of the sale of personal information (note: we do not sell personal
269
+ information)
270
+ </li>
271
+ <li>Right to non-discrimination for exercising your privacy rights</li>
272
+ </ul>
273
+ <p className="mt-2">
274
+ To exercise these rights, email{" "}
275
+ <a
276
+ href={`mailto:${brand.emails.privacy}`}
277
+ className="text-foreground underline underline-offset-4"
278
+ >
279
+ {brand.emails.privacy}
280
+ </a>
281
+ .
282
+ </p>
283
+ </section>
284
+
285
+ <section id="section-6" className="scroll-mt-16">
286
+ <h2 className="mb-2 text-base font-semibold text-foreground">6. Data Retention</h2>
287
+ <p>
288
+ We retain your account data for as long as your account is active. If you request
289
+ deletion of your account, we will delete your personal data within 30 days. Some
290
+ information may be retained longer where required by law:
291
+ </p>
292
+ <ul className="ml-4 mt-2 list-disc space-y-1">
293
+ <li>
294
+ Billing and transaction records are retained for up to 7 years as required by tax
295
+ and financial regulations
296
+ </li>
297
+ <li>Server logs are retained for 90 days</li>
298
+ <li>Backups containing your data are purged within 60 days of account deletion</li>
299
+ </ul>
300
+ </section>
301
+
302
+ <section id="section-7" className="scroll-mt-16">
303
+ <h2 className="mb-2 text-base font-semibold text-foreground">
304
+ 7. Cookies and Tracking
305
+ </h2>
306
+ <p>
307
+ We use essential cookies only. These cookies are required for authentication and
308
+ session management (powered by better-auth) and cannot be disabled without breaking
309
+ the service. We do not use marketing cookies, analytics cookies, or third-party
310
+ tracking pixels. There is no cookie banner because there is nothing optional to
311
+ consent to.
312
+ </p>
313
+ </section>
314
+
315
+ <section id="section-8" className="scroll-mt-16">
316
+ <h2 className="mb-2 text-base font-semibold text-foreground">8. Security</h2>
317
+ <p>
318
+ We take reasonable measures to protect your personal data. API keys are encrypted at
319
+ rest. All data in transit is protected via HTTPS. Access to production systems is
320
+ restricted to authorized personnel. We conduct regular security reviews of our
321
+ infrastructure and codebase. However, no method of transmission or storage is 100%
322
+ secure, and we cannot guarantee absolute security.
323
+ </p>
324
+ </section>
325
+
326
+ <section id="section-9" className="scroll-mt-16">
327
+ <h2 className="mb-2 text-base font-semibold text-foreground">
328
+ 9. International Data Transfers
329
+ </h2>
330
+ <p>
331
+ Your data may be processed in the United States or other countries where our
332
+ infrastructure providers operate. If you are located in the EU/EEA, transfers of your
333
+ personal data outside the EU/EEA are governed by Standard Contractual Clauses or
334
+ equivalent safeguards as required by GDPR.
335
+ </p>
336
+ </section>
337
+
338
+ <section id="section-10" className="scroll-mt-16">
339
+ <h2 className="mb-2 text-base font-semibold text-foreground">
340
+ 10. Data Breach Notification
341
+ </h2>
342
+ <p>
343
+ In the event of a data breach that is likely to result in a risk to your rights and
344
+ freedoms, we will notify affected users without undue delay. Where required by GDPR,
345
+ we will also notify the relevant supervisory authority within 72 hours of becoming
346
+ aware of the breach.
347
+ </p>
348
+ </section>
349
+
350
+ <section id="section-11" className="scroll-mt-16">
351
+ <h2 className="mb-2 text-base font-semibold text-foreground">
352
+ 11. Children&apos;s Privacy
353
+ </h2>
354
+ <p>
355
+ {brand.productName} is not intended for use by children under the age of 13. We do not
356
+ knowingly collect personal data from children under 13. If you believe a child under
357
+ 13 has provided us with personal data, please contact us at{" "}
358
+ <a
359
+ href={`mailto:${brand.emails.privacy}`}
360
+ className="text-foreground underline underline-offset-4"
361
+ >
362
+ {brand.emails.privacy}
363
+ </a>{" "}
364
+ and we will delete the data promptly.
365
+ </p>
366
+ </section>
367
+
368
+ <section id="section-12" className="scroll-mt-16">
369
+ <h2 className="mb-2 text-base font-semibold text-foreground">
370
+ 12. Changes to This Policy
371
+ </h2>
372
+ <p>
373
+ We may update this Privacy Policy from time to time. If we make material changes, we
374
+ will notify you by email or through a prominent notice on the service before the
375
+ changes take effect. Your continued use of {brand.productName} after the changes take
376
+ effect constitutes acceptance of the updated policy.
377
+ </p>
378
+ </section>
379
+
380
+ <section id="section-13" className="scroll-mt-16">
381
+ <h2 className="mb-2 text-base font-semibold text-foreground">13. Contact</h2>
382
+ <p>
383
+ Questions about this privacy policy? Email us at{" "}
384
+ <a
385
+ href={`mailto:${brand.emails.privacy}`}
386
+ className="text-foreground underline underline-offset-4"
387
+ >
388
+ {brand.emails.privacy}
389
+ </a>
390
+ .
391
+ </p>
392
+ </section>
393
+ </div>
394
+
395
+ <div className="mt-12 flex flex-wrap gap-4 text-sm text-muted-foreground">
396
+ <Link href="/terms" className="underline underline-offset-4 hover:text-foreground">
397
+ Terms of Service
398
+ </Link>
399
+ <Link href="/" className="underline underline-offset-4 hover:text-foreground">
400
+ Home
401
+ </Link>
402
+ </div>
403
+ </div>
404
+ </>
405
+ );
406
+ }
@@ -0,0 +1,9 @@
1
+ import type { MetadataRoute } from "next";
2
+ import { SITE_URL } from "@/lib/api-config";
3
+
4
+ export default function robots(): MetadataRoute.Robots {
5
+ return {
6
+ rules: { userAgent: "*", allow: "/" },
7
+ sitemap: `${SITE_URL}/sitemap.xml`,
8
+ };
9
+ }
@@ -0,0 +1,11 @@
1
+ import type { MetadataRoute } from "next";
2
+ import { SITE_URL } from "@/lib/api-config";
3
+
4
+ export default function sitemap(): MetadataRoute.Sitemap {
5
+ return [
6
+ { url: SITE_URL, lastModified: new Date() },
7
+ { url: `${SITE_URL}/pricing`, lastModified: new Date() },
8
+ { url: `${SITE_URL}/terms`, lastModified: new Date() },
9
+ { url: `${SITE_URL}/privacy`, lastModified: new Date() },
10
+ ];
11
+ }
@@ -0,0 +1,72 @@
1
+ "use client";
2
+
3
+ import { AlertTriangleIcon, HomeIcon, RefreshCwIcon } from "lucide-react";
4
+ import { useEffect, useState } from "react";
5
+ import { Button } from "@/components/ui/button";
6
+ import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
7
+ import { logger } from "@/lib/logger";
8
+
9
+ const log = logger("error-boundary:status");
10
+
11
+ export default function StatusError({
12
+ error,
13
+ reset,
14
+ }: {
15
+ error: Error & { digest?: string };
16
+ reset: () => void;
17
+ }) {
18
+ const [showDetails, setShowDetails] = useState(false);
19
+ const isDev = process.env.NODE_ENV === "development";
20
+
21
+ useEffect(() => {
22
+ log.error("Status error", error);
23
+ }, [error]);
24
+
25
+ return (
26
+ <div className="flex min-h-screen items-center justify-center p-6">
27
+ <Card className="w-full max-w-lg">
28
+ <CardHeader>
29
+ <div className="flex items-center gap-3">
30
+ <AlertTriangleIcon className="size-6 text-destructive" />
31
+ <CardTitle className="text-xl">Status Error</CardTitle>
32
+ </div>
33
+ </CardHeader>
34
+ <CardContent className="space-y-4">
35
+ <p className="text-muted-foreground">
36
+ Something went wrong loading system status. This may be a temporary issue.
37
+ </p>
38
+ {isDev && (
39
+ <Button
40
+ type="button"
41
+ variant="link"
42
+ size="sm"
43
+ onClick={() => setShowDetails((v) => !v)}
44
+ className="h-auto p-0 text-muted-foreground"
45
+ >
46
+ {showDetails ? "Hide" : "Show"} error details
47
+ </Button>
48
+ )}
49
+ {isDev && showDetails && (
50
+ <pre className="max-h-48 overflow-auto rounded-md border bg-muted p-3 text-xs">
51
+ {error.message}
52
+ {error.stack && `\n\n${error.stack}`}
53
+ {error.digest && `\n\nDigest: ${error.digest}`}
54
+ </pre>
55
+ )}
56
+ </CardContent>
57
+ <CardFooter className="gap-3">
58
+ <Button onClick={reset}>
59
+ <RefreshCwIcon />
60
+ Try Again
61
+ </Button>
62
+ <Button variant="outline" asChild>
63
+ <a href="/">
64
+ <HomeIcon />
65
+ Home
66
+ </a>
67
+ </Button>
68
+ </CardFooter>
69
+ </Card>
70
+ </div>
71
+ );
72
+ }
@@ -0,0 +1,21 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function StatusLoading() {
4
+ return (
5
+ <div className="space-y-6 p-6">
6
+ <div className="space-y-2">
7
+ <Skeleton className="h-8 w-48" />
8
+ <Skeleton className="h-4 w-64" />
9
+ </div>
10
+ <div className="rounded-sm border p-6 space-y-4">
11
+ <Skeleton className="h-5 w-32" />
12
+ {Array.from({ length: 5 }, (_, n) => `sk-${n}`).map((skId) => (
13
+ <div key={skId} className="flex items-center justify-between py-2">
14
+ <Skeleton className="h-4 w-32" />
15
+ <Skeleton className="h-4 w-20" />
16
+ </div>
17
+ ))}
18
+ </div>
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,20 @@
1
+ import type { Metadata } from "next";
2
+ import { StatusPage } from "@/components/status/status-page";
3
+ import { SITE_URL } from "@/lib/api-config";
4
+ import { getBrandConfig } from "@/lib/brand-config";
5
+
6
+ const brand = getBrandConfig();
7
+
8
+ export const metadata: Metadata = {
9
+ title: `Platform Status — ${brand.brandName}`,
10
+ description: `Real-time health and uptime status for the ${brand.brandName} platform.`,
11
+ openGraph: {
12
+ title: `Platform Status — ${brand.brandName}`,
13
+ description: `Real-time health and uptime status for the ${brand.brandName} platform.`,
14
+ url: `${SITE_URL}/status`,
15
+ },
16
+ };
17
+
18
+ export default function Page() {
19
+ return <StatusPage />;
20
+ }