@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.
- package/.env.paperclip +18 -0
- package/.env.wopr +18 -0
- package/README.md +36 -0
- package/biome.json +52 -0
- package/next.config.ts +45 -0
- package/package.json +84 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/window.svg +1 -0
- package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +741 -0
- package/src/__tests__/account-page-redirect.test.tsx +73 -0
- package/src/__tests__/account-switcher.test.tsx +85 -0
- package/src/__tests__/activity-page.test.tsx +176 -0
- package/src/__tests__/add-payment-method-dialog.test.tsx +160 -0
- package/src/__tests__/admin-api.test.ts +244 -0
- package/src/__tests__/admin-gpu-api.test.ts +188 -0
- package/src/__tests__/admin-guard.test.tsx +79 -0
- package/src/__tests__/admin-marketplace-api.test.ts +179 -0
- package/src/__tests__/admin-middleware.test.ts +157 -0
- package/src/__tests__/admin-tenant-table.test.tsx +95 -0
- package/src/__tests__/affiliate-dashboard.test.tsx +178 -0
- package/src/__tests__/api-401-redirect.test.ts +78 -0
- package/src/__tests__/api-client.test.ts +316 -0
- package/src/__tests__/api-config.test.ts +89 -0
- package/src/__tests__/api-control-instance.test.ts +69 -0
- package/src/__tests__/api-fleet-resources.test.ts +52 -0
- package/src/__tests__/api-fleet-trpc.test.ts +252 -0
- package/src/__tests__/api-get-instance-config.test.ts +41 -0
- package/src/__tests__/api-null-guards.test.ts +244 -0
- package/src/__tests__/api-rename-instance.test.ts +60 -0
- package/src/__tests__/api-update-instance-config.test.ts +60 -0
- package/src/__tests__/audit-log-table-pagination.test.tsx +136 -0
- package/src/__tests__/auth-client.test.ts +87 -0
- package/src/__tests__/auth-password-reset.test.tsx +435 -0
- package/src/__tests__/auth-redirect.test.tsx +60 -0
- package/src/__tests__/auth.test.tsx +269 -0
- package/src/__tests__/auto-topup-card.test.tsx +257 -0
- package/src/__tests__/backups-tab.test.tsx +221 -0
- package/src/__tests__/billing-byok-callout.test.tsx +76 -0
- package/src/__tests__/billing-layout-nav-hidden.test.tsx +47 -0
- package/src/__tests__/billing-payment-org-invoices.test.tsx +123 -0
- package/src/__tests__/billing.test.tsx +509 -0
- package/src/__tests__/bot-settings/resources-tab.test.tsx +119 -0
- package/src/__tests__/bot-settings/storage-tab.test.tsx +80 -0
- package/src/__tests__/bot-settings/vps-info-panel.test.tsx +108 -0
- package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +52 -0
- package/src/__tests__/bot-settings-data-control.test.ts +49 -0
- package/src/__tests__/bot-settings-restart.test.tsx +149 -0
- package/src/__tests__/bot-settings.test.tsx +678 -0
- package/src/__tests__/brand.test.ts +335 -0
- package/src/__tests__/buy-credits-panel.test.tsx +249 -0
- package/src/__tests__/buy-crypto-credits-panel.test.tsx +178 -0
- package/src/__tests__/capability-conflicts.test.ts +88 -0
- package/src/__tests__/capability-resolver.test.tsx +173 -0
- package/src/__tests__/changeset-detail.test.tsx +156 -0
- package/src/__tests__/channel-setup-logger.test.ts +22 -0
- package/src/__tests__/channel-setup-toast.test.tsx +60 -0
- package/src/__tests__/channel-wizard.test.tsx +505 -0
- package/src/__tests__/chat/ambient-dot.test.tsx +35 -0
- package/src/__tests__/chat/chat-input.test.tsx +78 -0
- package/src/__tests__/chat/chat-message.test.tsx +45 -0
- package/src/__tests__/chat/chat-panel.test.tsx +111 -0
- package/src/__tests__/chat/chat-widget.test.tsx +82 -0
- package/src/__tests__/chat-store.test.ts +87 -0
- package/src/__tests__/command-center.test.tsx +246 -0
- package/src/__tests__/compliance-retention-edit.test.tsx +134 -0
- package/src/__tests__/coupon-input.test.tsx +119 -0
- package/src/__tests__/create-instance.test.tsx +96 -0
- package/src/__tests__/create-org-wizard.test.tsx +200 -0
- package/src/__tests__/credit-balance.test.tsx +103 -0
- package/src/__tests__/credits.test.tsx +376 -0
- package/src/__tests__/csrf-middleware.test.ts +198 -0
- package/src/__tests__/degraded-state-banner.test.tsx +130 -0
- package/src/__tests__/dividend-calculator.test.tsx +20 -0
- package/src/__tests__/dividend-stats.test.tsx +64 -0
- package/src/__tests__/dividend.test.tsx +169 -0
- package/src/__tests__/dockerfile.test.ts +110 -0
- package/src/__tests__/email-verification-banner.test.tsx +64 -0
- package/src/__tests__/env-example.test.ts +25 -0
- package/src/__tests__/error-boundaries.test.tsx +64 -0
- package/src/__tests__/fetch-pricing.test.ts +121 -0
- package/src/__tests__/field-oauth.test.tsx +302 -0
- package/src/__tests__/fixtures/mock-manifests-data.js +372 -0
- package/src/__tests__/fixtures/mock-manifests.ts +24 -0
- package/src/__tests__/fleet-health-timestamp.test.tsx +101 -0
- package/src/__tests__/fleet-health-update.test.tsx +83 -0
- package/src/__tests__/format-credit.test.ts +58 -0
- package/src/__tests__/gpu-dashboard.test.tsx +236 -0
- package/src/__tests__/hosted-usage-date-range.test.tsx +54 -0
- package/src/__tests__/instance-detail.test.tsx +571 -0
- package/src/__tests__/instance-list.test.tsx +230 -0
- package/src/__tests__/landing-hero.test.tsx +27 -0
- package/src/__tests__/landing-nav.test.tsx +24 -0
- package/src/__tests__/layout-snapshots.test.tsx +167 -0
- package/src/__tests__/logger.test.ts +54 -0
- package/src/__tests__/login-page-redirect.test.tsx +142 -0
- package/src/__tests__/manifest-validation.test.ts +126 -0
- package/src/__tests__/marketplace-admin.test.tsx +151 -0
- package/src/__tests__/marketplace.test.tsx +609 -0
- package/src/__tests__/merge-api-rates.test.ts +70 -0
- package/src/__tests__/middleware.test.ts +690 -0
- package/src/__tests__/network-page.test.tsx +100 -0
- package/src/__tests__/next-config-headers.test.ts +28 -0
- package/src/__tests__/not-found.test.tsx +26 -0
- package/src/__tests__/notifications.test.tsx +128 -0
- package/src/__tests__/oauth-buttons.test.tsx +101 -0
- package/src/__tests__/oauth-error-mapping.test.tsx +97 -0
- package/src/__tests__/observability.test.tsx +541 -0
- package/src/__tests__/onboarding-data.test.ts +363 -0
- package/src/__tests__/onboarding-page.test.tsx +113 -0
- package/src/__tests__/onboarding-store.test.ts +121 -0
- package/src/__tests__/org-billing-api.test.tsx +70 -0
- package/src/__tests__/org-billing-null-guards.test.ts +64 -0
- package/src/__tests__/org-billing-page.test.tsx +124 -0
- package/src/__tests__/plugin-definition.test.ts +43 -0
- package/src/__tests__/plugin-install-flow.test.tsx +535 -0
- package/src/__tests__/plugin-registry.test.tsx +475 -0
- package/src/__tests__/plugin-setup/setup-chat-panel.test.ts +142 -0
- package/src/__tests__/plugin-setup/use-plugin-setup-chat.test.ts +49 -0
- package/src/__tests__/plugin-tool-definitions.test.ts +51 -0
- package/src/__tests__/plugin-tool-sync.test.ts +59 -0
- package/src/__tests__/portfolio-chart.test.tsx +24 -0
- package/src/__tests__/pricing.test.tsx +107 -0
- package/src/__tests__/promotion-form.test.tsx +180 -0
- package/src/__tests__/promotions-list.test.tsx +194 -0
- package/src/__tests__/provider-key-api.test.ts +134 -0
- package/src/__tests__/resend-verification-button.test.tsx +104 -0
- package/src/__tests__/sanitize-redirect-url.test.ts +47 -0
- package/src/__tests__/secrets-audit-pagination.test.tsx +139 -0
- package/src/__tests__/settings.test.tsx +937 -0
- package/src/__tests__/setup-checklist.test.tsx +274 -0
- package/src/__tests__/setup.ts +82 -0
- package/src/__tests__/smoke.test.tsx +10 -0
- package/src/__tests__/snapshot-api.test.ts +104 -0
- package/src/__tests__/status-api.test.ts +46 -0
- package/src/__tests__/status-badge.test.tsx +33 -0
- package/src/__tests__/status-colors.test.ts +83 -0
- package/src/__tests__/status-page.test.tsx +86 -0
- package/src/__tests__/step-superpowers.test.tsx +218 -0
- package/src/__tests__/story-sections.test.tsx +24 -0
- package/src/__tests__/superpower-content-sanitize.test.tsx +87 -0
- package/src/__tests__/superpower-content.test.tsx +44 -0
- package/src/__tests__/suspension-banner.test.tsx +140 -0
- package/src/__tests__/tenant-context.test.tsx +146 -0
- package/src/__tests__/tenant-keys-api.test.ts +114 -0
- package/src/__tests__/tenant-table-pagination.test.tsx +124 -0
- package/src/__tests__/terminal-log-cleanup.test.tsx +51 -0
- package/src/__tests__/terminal-sequence.test.tsx +28 -0
- package/src/__tests__/transaction-history.test.tsx +325 -0
- package/src/__tests__/trpc-types.test.ts +102 -0
- package/src/__tests__/use-capability-meta.test.ts +161 -0
- package/src/__tests__/use-chat.test.ts +616 -0
- package/src/__tests__/use-has-org.test.ts +44 -0
- package/src/__tests__/use-image-status.test.ts +77 -0
- package/src/__tests__/use-pagination-params.test.ts +88 -0
- package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +53 -0
- package/src/__tests__/use-webmcp.test.ts +119 -0
- package/src/__tests__/validate-elevenlabs-key.test.ts +95 -0
- package/src/__tests__/validate-redirect-url.test.ts +61 -0
- package/src/__tests__/verify-page.test.tsx +140 -0
- package/src/__tests__/verify-redirect.test.tsx +41 -0
- package/src/__tests__/verify-result-banner.test.tsx +66 -0
- package/src/__tests__/webmcp-feature-detect.test.ts +54 -0
- package/src/__tests__/webmcp-hook.test.tsx +72 -0
- package/src/__tests__/webmcp-marketplace-onboarding-tools.test.ts +185 -0
- package/src/__tests__/webmcp-register.test.ts +103 -0
- package/src/__tests__/webmcp-set-provider.test.ts +47 -0
- package/src/__tests__/webmcp-tools.test.ts +348 -0
- package/src/app/(auth)/error.tsx +72 -0
- package/src/app/(auth)/forgot-password/page.tsx +137 -0
- package/src/app/(auth)/layout.tsx +14 -0
- package/src/app/(auth)/loading.tsx +26 -0
- package/src/app/(auth)/login/page.tsx +188 -0
- package/src/app/(auth)/reset-password/page.tsx +169 -0
- package/src/app/(auth)/signup/page.tsx +309 -0
- package/src/app/(dashboard)/billing/credits/page.tsx +209 -0
- package/src/app/(dashboard)/billing/error.tsx +72 -0
- package/src/app/(dashboard)/billing/layout.tsx +73 -0
- package/src/app/(dashboard)/billing/loading.tsx +41 -0
- package/src/app/(dashboard)/billing/payment/page.tsx +639 -0
- package/src/app/(dashboard)/billing/plans/page.tsx +58 -0
- package/src/app/(dashboard)/billing/referrals/page.tsx +7 -0
- package/src/app/(dashboard)/billing/usage/hosted/page.tsx +348 -0
- package/src/app/(dashboard)/billing/usage/page.tsx +663 -0
- package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +400 -0
- package/src/app/(dashboard)/changesets/[id]/error.tsx +57 -0
- package/src/app/(dashboard)/changesets/[id]/loading.tsx +23 -0
- package/src/app/(dashboard)/changesets/[id]/page.tsx +10 -0
- package/src/app/(dashboard)/changesets/error.tsx +72 -0
- package/src/app/(dashboard)/changesets/page.tsx +10 -0
- package/src/app/(dashboard)/chat/page.tsx +74 -0
- package/src/app/(dashboard)/dashboard/bots/[id]/settings/page.tsx +10 -0
- package/src/app/(dashboard)/dashboard/network/page.tsx +97 -0
- package/src/app/(dashboard)/dashboard/page.tsx +13 -0
- package/src/app/(dashboard)/error.tsx +72 -0
- package/src/app/(dashboard)/layout.tsx +113 -0
- package/src/app/(dashboard)/loading.tsx +27 -0
- package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +548 -0
- package/src/app/(dashboard)/marketplace/error.tsx +72 -0
- package/src/app/(dashboard)/marketplace/loading.tsx +27 -0
- package/src/app/(dashboard)/marketplace/page.tsx +268 -0
- package/src/app/(dashboard)/not-found.tsx +46 -0
- package/src/app/(dashboard)/onboarding/page.tsx +267 -0
- package/src/app/(dashboard)/settings/account/page.tsx +132 -0
- package/src/app/(dashboard)/settings/activity/page.tsx +280 -0
- package/src/app/(dashboard)/settings/api-keys/page.tsx +530 -0
- package/src/app/(dashboard)/settings/brain/page.tsx +412 -0
- package/src/app/(dashboard)/settings/error.tsx +72 -0
- package/src/app/(dashboard)/settings/layout.tsx +114 -0
- package/src/app/(dashboard)/settings/loading.tsx +31 -0
- package/src/app/(dashboard)/settings/notifications/page.tsx +216 -0
- package/src/app/(dashboard)/settings/org/page.tsx +617 -0
- package/src/app/(dashboard)/settings/profile/page.tsx +510 -0
- package/src/app/(dashboard)/settings/providers/page.tsx +842 -0
- package/src/app/(dashboard)/settings/secrets/page.tsx +658 -0
- package/src/app/(dashboard)/settings/security/page.tsx +1133 -0
- package/src/app/admin/accounting/loading.tsx +32 -0
- package/src/app/admin/accounting/page.tsx +5 -0
- package/src/app/admin/affiliates/loading.tsx +32 -0
- package/src/app/admin/affiliates/page.tsx +5 -0
- package/src/app/admin/audit/loading.tsx +32 -0
- package/src/app/admin/audit/page.tsx +5 -0
- package/src/app/admin/billing-health/loading.tsx +17 -0
- package/src/app/admin/billing-health/page.tsx +10 -0
- package/src/app/admin/compliance/page.tsx +5 -0
- package/src/app/admin/error.tsx +72 -0
- package/src/app/admin/gpu/loading.tsx +38 -0
- package/src/app/admin/gpu/page.tsx +5 -0
- package/src/app/admin/incidents/page.tsx +10 -0
- package/src/app/admin/inference/loading.tsx +32 -0
- package/src/app/admin/inference/page.tsx +5 -0
- package/src/app/admin/layout.tsx +44 -0
- package/src/app/admin/loading.tsx +32 -0
- package/src/app/admin/marketplace/loading.tsx +32 -0
- package/src/app/admin/marketplace/page.tsx +5 -0
- package/src/app/admin/migrations/loading.tsx +22 -0
- package/src/app/admin/migrations/page.tsx +5 -0
- package/src/app/admin/onboarding/loading.tsx +18 -0
- package/src/app/admin/onboarding/page.tsx +5 -0
- package/src/app/admin/promotions/[id]/edit/loading.tsx +16 -0
- package/src/app/admin/promotions/[id]/edit/page.tsx +56 -0
- package/src/app/admin/promotions/[id]/loading.tsx +15 -0
- package/src/app/admin/promotions/[id]/page.tsx +311 -0
- package/src/app/admin/promotions/loading.tsx +21 -0
- package/src/app/admin/promotions/new/loading.tsx +16 -0
- package/src/app/admin/promotions/new/page.tsx +12 -0
- package/src/app/admin/promotions/page.tsx +266 -0
- package/src/app/admin/rate-overrides/loading.tsx +17 -0
- package/src/app/admin/rate-overrides/page.tsx +290 -0
- package/src/app/admin/roles/loading.tsx +27 -0
- package/src/app/admin/roles/page.tsx +5 -0
- package/src/app/admin/tenants/loading.tsx +32 -0
- package/src/app/admin/tenants/page.tsx +5 -0
- package/src/app/apple-icon.tsx +32 -0
- package/src/app/auth/callback/[provider]/page.tsx +104 -0
- package/src/app/auth/verify/page.tsx +224 -0
- package/src/app/channels/error.tsx +72 -0
- package/src/app/channels/loading.tsx +29 -0
- package/src/app/channels/page.tsx +262 -0
- package/src/app/channels/setup/[plugin]/page.tsx +136 -0
- package/src/app/error.tsx +72 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/fleet/error.tsx +72 -0
- package/src/app/fleet/health/page.tsx +9 -0
- package/src/app/fleet/layout.tsx +14 -0
- package/src/app/fleet/loading.tsx +33 -0
- package/src/app/fleet/page.tsx +5 -0
- package/src/app/global-error.tsx +96 -0
- package/src/app/globals.css +251 -0
- package/src/app/icon.svg +4 -0
- package/src/app/instances/[id]/instance-detail-client.tsx +1298 -0
- package/src/app/instances/[id]/page.tsx +10 -0
- package/src/app/instances/error.tsx +72 -0
- package/src/app/instances/instance-list-client.tsx +540 -0
- package/src/app/instances/loading.tsx +33 -0
- package/src/app/instances/new/create-instance-client.tsx +377 -0
- package/src/app/instances/new/page.tsx +9 -0
- package/src/app/instances/page.tsx +9 -0
- package/src/app/layout.tsx +83 -0
- package/src/app/not-found.tsx +38 -0
- package/src/app/og/route.tsx +50 -0
- package/src/app/page.tsx +39 -0
- package/src/app/plugins/error.tsx +72 -0
- package/src/app/plugins/layout.tsx +14 -0
- package/src/app/plugins/loading.tsx +30 -0
- package/src/app/plugins/page.tsx +555 -0
- package/src/app/pricing/error.tsx +72 -0
- package/src/app/pricing/loading.tsx +25 -0
- package/src/app/pricing/page.tsx +20 -0
- package/src/app/privacy/page.tsx +406 -0
- package/src/app/robots.ts +9 -0
- package/src/app/sitemap.ts +11 -0
- package/src/app/status/error.tsx +72 -0
- package/src/app/status/loading.tsx +21 -0
- package/src/app/status/page.tsx +20 -0
- package/src/app/terms/page.tsx +414 -0
- package/src/components/account-switcher.tsx +82 -0
- package/src/components/admin/accounting-dashboard.tsx +190 -0
- package/src/components/admin/admin-guard.tsx +36 -0
- package/src/components/admin/admin-nav.tsx +71 -0
- package/src/components/admin/affiliate-dashboard.tsx +564 -0
- package/src/components/admin/audit-log-table.tsx +336 -0
- package/src/components/admin/billing-health-dashboard.test.tsx +40 -0
- package/src/components/admin/billing-health-dashboard.tsx +416 -0
- package/src/components/admin/bulk-actions-bar.test.tsx +92 -0
- package/src/components/admin/bulk-actions-bar.tsx +80 -0
- package/src/components/admin/bulk-export-dialog.test.tsx +75 -0
- package/src/components/admin/bulk-export-dialog.tsx +189 -0
- package/src/components/admin/bulk-grant-dialog.test.tsx +81 -0
- package/src/components/admin/bulk-grant-dialog.tsx +147 -0
- package/src/components/admin/bulk-preview-dialog.test.tsx +72 -0
- package/src/components/admin/bulk-preview-dialog.tsx +106 -0
- package/src/components/admin/bulk-reactivate-dialog.test.tsx +51 -0
- package/src/components/admin/bulk-reactivate-dialog.tsx +55 -0
- package/src/components/admin/bulk-select-all-banner.test.tsx +36 -0
- package/src/components/admin/bulk-select-all-banner.tsx +44 -0
- package/src/components/admin/bulk-suspend-dialog.test.tsx +77 -0
- package/src/components/admin/bulk-suspend-dialog.tsx +129 -0
- package/src/components/admin/bulk-undo-toast.test.tsx +66 -0
- package/src/components/admin/bulk-undo-toast.tsx +121 -0
- package/src/components/admin/compliance-dashboard.tsx +1341 -0
- package/src/components/admin/gpu-dashboard.tsx +552 -0
- package/src/components/admin/grant-credits-dialog.tsx +121 -0
- package/src/components/admin/incident-dashboard.test.tsx +44 -0
- package/src/components/admin/incident-dashboard.tsx +717 -0
- package/src/components/admin/inference-dashboard.tsx +415 -0
- package/src/components/admin/marketplace-admin.tsx +765 -0
- package/src/components/admin/migrations-dashboard.tsx +404 -0
- package/src/components/admin/onboarding-dashboard.tsx +422 -0
- package/src/components/admin/promotions/promotion-form.tsx +440 -0
- package/src/components/admin/roles-dashboard.tsx +278 -0
- package/src/components/admin/suspend-dialog.tsx +98 -0
- package/src/components/admin/tenant-notes-panel.tsx +134 -0
- package/src/components/admin/tenant-row-actions.tsx +78 -0
- package/src/components/admin/tenant-table.tsx +339 -0
- package/src/components/auth/auth-error.tsx +22 -0
- package/src/components/auth/auth-redirect.tsx +18 -0
- package/src/components/auth/auth-shell.tsx +25 -0
- package/src/components/auth/email-verification-banner.tsx +25 -0
- package/src/components/auth/email-verification-result-banner.tsx +70 -0
- package/src/components/auth/resend-verification-button.tsx +94 -0
- package/src/components/auth/wopr-wordmark.tsx +19 -0
- package/src/components/billing/add-payment-method-dialog.tsx +267 -0
- package/src/components/billing/affiliate-dashboard.tsx +300 -0
- package/src/components/billing/auto-topup-card.tsx +432 -0
- package/src/components/billing/buy-credits-panel.tsx +180 -0
- package/src/components/billing/buy-crypto-credits-panel.tsx +96 -0
- package/src/components/billing/byok-callout.tsx +87 -0
- package/src/components/billing/coupon-input.tsx +86 -0
- package/src/components/billing/credit-balance.tsx +79 -0
- package/src/components/billing/degraded-state-banner.tsx +95 -0
- package/src/components/billing/dividend-banner.tsx +97 -0
- package/src/components/billing/dividend-eligibility.tsx +86 -0
- package/src/components/billing/dividend-pool-stats.tsx +86 -0
- package/src/components/billing/first-dividend-dialog.tsx +109 -0
- package/src/components/billing/low-balance-banner.tsx +50 -0
- package/src/components/billing/org-billing-page.tsx +360 -0
- package/src/components/billing/suspension-banner.tsx +53 -0
- package/src/components/billing/transaction-history.tsx +239 -0
- package/src/components/bot-settings/__tests__/bot-settings-client.test.tsx +205 -0
- package/src/components/bot-settings/backups-tab.tsx +377 -0
- package/src/components/bot-settings/bot-settings-client.tsx +1712 -0
- package/src/components/bot-settings/resources-tab.tsx +203 -0
- package/src/components/bot-settings/storage-tab.tsx +248 -0
- package/src/components/bot-settings/vps-info-panel.tsx +132 -0
- package/src/components/bot-settings/vps-upgrade-card.tsx +110 -0
- package/src/components/capability/CapabilityResolver.tsx +113 -0
- package/src/components/channel-wizard/field-interactive.tsx +48 -0
- package/src/components/channel-wizard/field-oauth.tsx +181 -0
- package/src/components/channel-wizard/field-paste.tsx +47 -0
- package/src/components/channel-wizard/field-qr.tsx +302 -0
- package/src/components/channel-wizard/index.ts +6 -0
- package/src/components/channel-wizard/step-renderer.tsx +103 -0
- package/src/components/channel-wizard/wizard.tsx +200 -0
- package/src/components/chat/ambient-dot.tsx +32 -0
- package/src/components/chat/chat-input.tsx +56 -0
- package/src/components/chat/chat-message.tsx +36 -0
- package/src/components/chat/chat-panel.tsx +138 -0
- package/src/components/chat/chat-widget.tsx +41 -0
- package/src/components/chat/index.ts +5 -0
- package/src/components/dashboard/command-center.tsx +614 -0
- package/src/components/instances/friends-tab.test.tsx +265 -0
- package/src/components/instances/friends-tab.tsx +721 -0
- package/src/components/landing/hero.tsx +53 -0
- package/src/components/landing/landing-nav.tsx +21 -0
- package/src/components/landing/landing-page.tsx +71 -0
- package/src/components/landing/portfolio-chart.tsx +349 -0
- package/src/components/landing/story-sections.tsx +50 -0
- package/src/components/landing/terminal-lines.ts +99 -0
- package/src/components/landing/terminal-sequence.tsx +453 -0
- package/src/components/landing/typing-effect.tsx +43 -0
- package/src/components/marketplace/category-filter.tsx +61 -0
- package/src/components/marketplace/empty-state.tsx +61 -0
- package/src/components/marketplace/featured-heroes.tsx +84 -0
- package/src/components/marketplace/first-visit-hero.tsx +110 -0
- package/src/components/marketplace/index.ts +9 -0
- package/src/components/marketplace/install-wizard.tsx +782 -0
- package/src/components/marketplace/marketplace-tabs.tsx +54 -0
- package/src/components/marketplace/plugin-card.tsx +129 -0
- package/src/components/marketplace/superpower-card.tsx +104 -0
- package/src/components/marketplace/superpower-content.tsx +117 -0
- package/src/components/marketplace/terminal-search.tsx +67 -0
- package/src/components/oauth-buttons.tsx +75 -0
- package/src/components/observability/fleet-health.tsx +370 -0
- package/src/components/observability/health-overview.tsx +246 -0
- package/src/components/observability/logs-viewer.tsx +215 -0
- package/src/components/observability/metrics-dashboard.tsx +288 -0
- package/src/components/onboarding/fallback-setup.tsx +137 -0
- package/src/components/onboarding/index.ts +3 -0
- package/src/components/onboarding/setup-checklist.tsx +333 -0
- package/src/components/onboarding/step-superpowers.tsx +122 -0
- package/src/components/plugin-setup/index.ts +1 -0
- package/src/components/plugin-setup/setup-chat-panel.tsx +188 -0
- package/src/components/pricing/dividend-calculator.tsx +47 -0
- package/src/components/pricing/dividend-stats.tsx +117 -0
- package/src/components/pricing/pricing-page.tsx +229 -0
- package/src/components/settings/create-org-wizard.tsx +225 -0
- package/src/components/sidebar.tsx +202 -0
- package/src/components/status/status-page.tsx +209 -0
- package/src/components/status-badge.tsx +28 -0
- package/src/components/theme-provider.tsx +8 -0
- package/src/components/ui/alert-dialog.tsx +141 -0
- package/src/components/ui/badge.tsx +47 -0
- package/src/components/ui/banner.tsx +36 -0
- package/src/components/ui/button.tsx +64 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/checkbox.tsx +52 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/credit-detailed.tsx +33 -0
- package/src/components/ui/dialog.tsx +143 -0
- package/src/components/ui/dropdown-menu.tsx +228 -0
- package/src/components/ui/form.tsx +151 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +21 -0
- package/src/components/ui/popover.tsx +74 -0
- package/src/components/ui/progress.tsx +28 -0
- package/src/components/ui/radio-group.tsx +45 -0
- package/src/components/ui/select.tsx +175 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +125 -0
- package/src/components/ui/skeleton.tsx +15 -0
- package/src/components/ui/switch.tsx +35 -0
- package/src/components/ui/table.tsx +92 -0
- package/src/components/ui/tabs.tsx +81 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +44 -0
- package/src/config/provider-docs.ts +17 -0
- package/src/hooks/__tests__/use-async.test.ts +127 -0
- package/src/hooks/__tests__/use-count-up.test.ts +129 -0
- package/src/hooks/__tests__/use-debounce.test.ts +105 -0
- package/src/hooks/__tests__/use-fleet-sse.test.ts +216 -0
- package/src/hooks/__tests__/use-local-storage.test.ts +74 -0
- package/src/hooks/__tests__/use-mobile.test.ts +86 -0
- package/src/hooks/__tests__/use-save-queue.test.ts +159 -0
- package/src/hooks/use-async.ts +54 -0
- package/src/hooks/use-capability-meta.ts +99 -0
- package/src/hooks/use-count-up.ts +23 -0
- package/src/hooks/use-debounce.ts +12 -0
- package/src/hooks/use-fleet-sse.ts +47 -0
- package/src/hooks/use-has-org.ts +18 -0
- package/src/hooks/use-image-status.ts +36 -0
- package/src/hooks/use-local-storage.ts +36 -0
- package/src/hooks/use-mobile.ts +17 -0
- package/src/hooks/use-page-context.ts +24 -0
- package/src/hooks/use-pagination-params.ts +30 -0
- package/src/hooks/use-plugin-registry.ts +247 -0
- package/src/hooks/use-plugin-setup-chat.ts +211 -0
- package/src/hooks/use-save-queue.ts +54 -0
- package/src/hooks/use-webmcp.ts +40 -0
- package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +112 -0
- package/src/lib/__tests__/admin-api.test.ts +487 -0
- package/src/lib/__tests__/api-bot-crud.test.ts +391 -0
- package/src/lib/__tests__/api-fetch.test.ts +196 -0
- package/src/lib/__tests__/bot-settings-data.test.ts +352 -0
- package/src/lib/__tests__/org-api.test.ts +281 -0
- package/src/lib/__tests__/org-billing-api.test.ts +242 -0
- package/src/lib/__tests__/pricing-data.test.ts +32 -0
- package/src/lib/__tests__/settings-api.test.ts +272 -0
- package/src/lib/admin-affiliate-api.ts +51 -0
- package/src/lib/admin-api.ts +325 -0
- package/src/lib/admin-compliance-api.ts +127 -0
- package/src/lib/admin-gpu-api.ts +82 -0
- package/src/lib/admin-incident-api.ts +121 -0
- package/src/lib/admin-inference-api.ts +47 -0
- package/src/lib/admin-marketplace-api.ts +97 -0
- package/src/lib/api-config.test.ts +111 -0
- package/src/lib/api-config.ts +65 -0
- package/src/lib/api-errors.test.ts +43 -0
- package/src/lib/api.ts +2011 -0
- package/src/lib/auth-client.ts +11 -0
- package/src/lib/bot-settings-data.ts +342 -0
- package/src/lib/brand-config.ts +145 -0
- package/src/lib/brand.ts +669 -0
- package/src/lib/changeset-api.ts +29 -0
- package/src/lib/changeset-types.ts +56 -0
- package/src/lib/channel-manifests.ts +50 -0
- package/src/lib/chat/chat-context.tsx +70 -0
- package/src/lib/chat/chat-store.ts +62 -0
- package/src/lib/chat/types.ts +35 -0
- package/src/lib/chat/use-chat.ts +255 -0
- package/src/lib/cost-comparison-data.test.ts +95 -0
- package/src/lib/cost-comparison-data.ts +54 -0
- package/src/lib/errors.test.ts +64 -0
- package/src/lib/errors.ts +52 -0
- package/src/lib/fetch-utils.test.ts +57 -0
- package/src/lib/fetch-utils.ts +25 -0
- package/src/lib/format-credit.test.ts +66 -0
- package/src/lib/format-credit.ts +24 -0
- package/src/lib/format.test.ts +62 -0
- package/src/lib/format.ts +17 -0
- package/src/lib/logger.ts +28 -0
- package/src/lib/marketplace-data.ts +346 -0
- package/src/lib/oauth-errors.ts +19 -0
- package/src/lib/onboarding-data.ts +1265 -0
- package/src/lib/onboarding-store.ts +233 -0
- package/src/lib/org-api.ts +74 -0
- package/src/lib/org-billing-api.ts +81 -0
- package/src/lib/page-prompts.test.ts +32 -0
- package/src/lib/page-prompts.ts +23 -0
- package/src/lib/plugin/index.ts +32 -0
- package/src/lib/plugin/tool-definitions.ts +306 -0
- package/src/lib/pricing-data.ts +115 -0
- package/src/lib/promotions-types.ts +58 -0
- package/src/lib/settings-api.ts +63 -0
- package/src/lib/status-colors.ts +38 -0
- package/src/lib/tenant-context.tsx +134 -0
- package/src/lib/trpc-types.ts +173 -0
- package/src/lib/trpc.tsx +86 -0
- package/src/lib/utils.test.ts +55 -0
- package/src/lib/utils.ts +18 -0
- package/src/lib/validate-redirect-url.ts +39 -0
- package/src/lib/webmcp/feature-detect.ts +13 -0
- package/src/lib/webmcp/marketplace-onboarding-tools.ts +202 -0
- package/src/lib/webmcp/register.ts +44 -0
- package/src/lib/webmcp/tools.ts +422 -0
- package/src/proxy.ts +258 -0
- package/src/types/missing-deps.d.ts +160 -0
- package/src/types/motion-dom.d.ts +162 -0
- package/src/types/vitest-matchers.d.ts +40 -0
- package/src/types/web-mcp.d.ts +22 -0
- package/tsconfig.json +34 -0
- package/vitest.config.ts +26 -0
package/src/lib/brand.ts
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand Bible
|
|
3
|
+
*
|
|
4
|
+
* The rulebook. Every pixel, every word, every interaction
|
|
5
|
+
* references this file. Nothing ships without it.
|
|
6
|
+
*
|
|
7
|
+
* READ THIS FIRST. Then build.
|
|
8
|
+
*
|
|
9
|
+
* This file uses brand-config for all product/brand references.
|
|
10
|
+
* Each brand deployment (WOPR, Paperclip, etc.) sets its own
|
|
11
|
+
* config and the brand bible adapts automatically.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { brandName, getBrandConfig, productName } from "./brand-config";
|
|
15
|
+
|
|
16
|
+
// ===========================================================================
|
|
17
|
+
// THE VISION
|
|
18
|
+
// ===========================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The gap between what it costs and what it does — that IS the brand.
|
|
22
|
+
* Every piece of copy, every UI decision, every interaction should widen
|
|
23
|
+
* that gap. Make the user feel like they're getting away with something.
|
|
24
|
+
*
|
|
25
|
+
* We sell world domination at pocket-money prices.
|
|
26
|
+
*/
|
|
27
|
+
export function getVision() {
|
|
28
|
+
const name = productName();
|
|
29
|
+
const config = getBrandConfig();
|
|
30
|
+
return {
|
|
31
|
+
oneLiner: `A ${config.price || "$5/month"} supercomputer that manages your business.`,
|
|
32
|
+
question: `What would you do with your own ${name}?`,
|
|
33
|
+
sells: [
|
|
34
|
+
"Run a company while you sleep.",
|
|
35
|
+
"Replace yourself at your job. Keep the paycheck.",
|
|
36
|
+
"Build something that makes money without you.",
|
|
37
|
+
"Have an employee that never quits, never sleeps, never asks for a raise.",
|
|
38
|
+
"A supercomputer in your pocket for less than a coffee.",
|
|
39
|
+
],
|
|
40
|
+
doesNotSell: [
|
|
41
|
+
"AI capabilities",
|
|
42
|
+
"Automation workflows",
|
|
43
|
+
"Agent orchestration",
|
|
44
|
+
"LLM integration",
|
|
45
|
+
"Cloud infrastructure",
|
|
46
|
+
],
|
|
47
|
+
absurdityGap: {
|
|
48
|
+
what: "A supercomputer that runs your business",
|
|
49
|
+
cost: config.price || "$5/month",
|
|
50
|
+
emotion: "How is this even legal?",
|
|
51
|
+
mechanic:
|
|
52
|
+
"Every piece of marketing widens the gap between power and price. " +
|
|
53
|
+
"Show something massive. Then reveal the price. The contrast does the selling.",
|
|
54
|
+
},
|
|
55
|
+
world:
|
|
56
|
+
`A world where anyone with ${config.price || "$5/month"} and an idea can have an army of AI workers ` +
|
|
57
|
+
`running their business 24/7. No code. No infrastructure. No employees. ` +
|
|
58
|
+
`Just a ${name} and a credit card.`,
|
|
59
|
+
competitiveReality: {
|
|
60
|
+
them: {
|
|
61
|
+
setup: "$10,000 Mac Mini build",
|
|
62
|
+
gets: "5 agents running in parallel",
|
|
63
|
+
requires: "Hardware, electricity, maintenance, config, babysitting",
|
|
64
|
+
audience: "Rich hobbyists and AI Twitter influencers",
|
|
65
|
+
},
|
|
66
|
+
us: {
|
|
67
|
+
setup: "$50/month (5 bots at $5 + ~$25 LLM compute)",
|
|
68
|
+
gets: `5 ${name}s running in parallel. Same thing.`,
|
|
69
|
+
requires: "A credit card",
|
|
70
|
+
audience: "Everyone else",
|
|
71
|
+
},
|
|
72
|
+
math: {
|
|
73
|
+
theirCost: 10_000,
|
|
74
|
+
ourMonthlyCost: 50,
|
|
75
|
+
monthsToBreakEven: 200,
|
|
76
|
+
yearsToBreakEven: 16.7,
|
|
77
|
+
costRatio: "200x cheaper to start",
|
|
78
|
+
punchline: "Their hardware depreciates. Ours gets better every month.",
|
|
79
|
+
},
|
|
80
|
+
usage:
|
|
81
|
+
"Never name-drop Mac Mini or specific competitors in official copy. " +
|
|
82
|
+
"Instead, make the audience do the math themselves. " +
|
|
83
|
+
`Show what 5 ${name}s can do. Show the price. ` +
|
|
84
|
+
"They'll screenshot it and send it to the group chat where " +
|
|
85
|
+
"their friend just posted their $10K build. That's the play.",
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** @deprecated Use `getVision()` instead — static version reads defaults at import time. */
|
|
91
|
+
export const vision = getVision();
|
|
92
|
+
|
|
93
|
+
// ===========================================================================
|
|
94
|
+
// WHAT IS THE PRODUCT?
|
|
95
|
+
// ===========================================================================
|
|
96
|
+
|
|
97
|
+
export const product = {
|
|
98
|
+
/** What it IS. Use these words. */
|
|
99
|
+
is: [
|
|
100
|
+
"A supercomputer",
|
|
101
|
+
"Your 24/7 employee",
|
|
102
|
+
"A business in a box",
|
|
103
|
+
"An army of AI workers",
|
|
104
|
+
"Your unfair advantage",
|
|
105
|
+
],
|
|
106
|
+
|
|
107
|
+
/** What it is NOT. Never use these. */
|
|
108
|
+
isNot: [
|
|
109
|
+
"A chatbot",
|
|
110
|
+
"An AI assistant",
|
|
111
|
+
"An automation tool",
|
|
112
|
+
"A platform",
|
|
113
|
+
"A SaaS product",
|
|
114
|
+
"An agent framework",
|
|
115
|
+
],
|
|
116
|
+
|
|
117
|
+
/** What it does. Always outcomes, never features. */
|
|
118
|
+
does: [
|
|
119
|
+
"Manages your Discord community",
|
|
120
|
+
"Answers your customers",
|
|
121
|
+
"Ships your code",
|
|
122
|
+
"Runs your social media",
|
|
123
|
+
"Handles your support tickets",
|
|
124
|
+
"Makes you money while you sleep",
|
|
125
|
+
],
|
|
126
|
+
|
|
127
|
+
/** The metaphors that work. */
|
|
128
|
+
metaphors: [
|
|
129
|
+
"It's like hiring a genius intern for $5/month. Except it never sleeps.",
|
|
130
|
+
"Think iPhone, not smartphone. Personal, not enterprise.",
|
|
131
|
+
"The nuclear launch button is the deploy button. You're in command.",
|
|
132
|
+
],
|
|
133
|
+
} as const;
|
|
134
|
+
|
|
135
|
+
// ===========================================================================
|
|
136
|
+
// PRODUCT NAME
|
|
137
|
+
// ===========================================================================
|
|
138
|
+
|
|
139
|
+
/** @deprecated Use `productName()` from brand-config instead. */
|
|
140
|
+
export function getProductName(): string {
|
|
141
|
+
return productName();
|
|
142
|
+
}
|
|
143
|
+
/** @deprecated Use `brandName()` from brand-config instead. */
|
|
144
|
+
export function getBrandName(): string {
|
|
145
|
+
return brandName();
|
|
146
|
+
}
|
|
147
|
+
/** @deprecated Use `getBrandConfig().domain` instead. */
|
|
148
|
+
export function getDomain(): string {
|
|
149
|
+
return getBrandConfig().domain;
|
|
150
|
+
}
|
|
151
|
+
/** @deprecated Use `getBrandConfig().tagline` instead. */
|
|
152
|
+
export function getTagline(): string {
|
|
153
|
+
return getBrandConfig().tagline;
|
|
154
|
+
}
|
|
155
|
+
/** @deprecated Use `getBrandConfig().price` instead. */
|
|
156
|
+
export function getPrice(): string {
|
|
157
|
+
return getBrandConfig().price;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Legacy constants — kept for backward compatibility.
|
|
162
|
+
* These read from the brand config at import time.
|
|
163
|
+
* Prefer the function forms above or direct brand-config imports.
|
|
164
|
+
*/
|
|
165
|
+
export const PRODUCT_NAME = getBrandConfig().productName;
|
|
166
|
+
export const BRAND_NAME = getBrandConfig().brandName;
|
|
167
|
+
export const DOMAIN = getBrandConfig().domain;
|
|
168
|
+
export const TAGLINE = getBrandConfig().tagline;
|
|
169
|
+
export const PRICE = getBrandConfig().price;
|
|
170
|
+
|
|
171
|
+
export function getNameRules() {
|
|
172
|
+
const name = productName();
|
|
173
|
+
const brand = brandName();
|
|
174
|
+
const domain = getBrandConfig().domain;
|
|
175
|
+
return {
|
|
176
|
+
correct: [name, `your ${name}`, `Get your ${name}`, `a ${name}`, domain],
|
|
177
|
+
incorrect: [
|
|
178
|
+
...(brand !== name ? [brand] : []),
|
|
179
|
+
`the ${brand} platform`,
|
|
180
|
+
`${brand} AI`,
|
|
181
|
+
`${brand} service`,
|
|
182
|
+
`${brand} tool`,
|
|
183
|
+
name.toLowerCase(),
|
|
184
|
+
],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** @deprecated Use `getNameRules()` instead. */
|
|
189
|
+
export const nameRules = getNameRules();
|
|
190
|
+
|
|
191
|
+
// ===========================================================================
|
|
192
|
+
// TARGET AUDIENCE
|
|
193
|
+
// ===========================================================================
|
|
194
|
+
|
|
195
|
+
export const audience = {
|
|
196
|
+
/** The person we're talking to. */
|
|
197
|
+
primary:
|
|
198
|
+
"23-year-old with a credit card, 14 half-finished repos, and a graveyard of Discord bots. " +
|
|
199
|
+
"They don't need to be sold. They need to be told it exists.",
|
|
200
|
+
|
|
201
|
+
/** The adjacent audience we capture. */
|
|
202
|
+
secondary:
|
|
203
|
+
"The kid who just saw someone's $10,000 Mac Mini AI build on Twitter " +
|
|
204
|
+
"and thought 'I wish I could afford that.' We're the answer. " +
|
|
205
|
+
"Same power, pocket-money price. They find us in the replies.",
|
|
206
|
+
|
|
207
|
+
/** What motivates them. */
|
|
208
|
+
wants: [
|
|
209
|
+
"To build something that makes money",
|
|
210
|
+
"To feel like a founder without the risk",
|
|
211
|
+
"To automate the boring parts of their life",
|
|
212
|
+
"To have something running while they sleep",
|
|
213
|
+
"To flex on their friends",
|
|
214
|
+
"To have what the rich kids have, without the rich kid budget",
|
|
215
|
+
],
|
|
216
|
+
|
|
217
|
+
/** What they fear. */
|
|
218
|
+
fears: [
|
|
219
|
+
"Wasting money on something that doesn't work",
|
|
220
|
+
"Being too dumb to set it up",
|
|
221
|
+
"It being a scam / too good to be true",
|
|
222
|
+
],
|
|
223
|
+
|
|
224
|
+
/** How we neutralize those fears. */
|
|
225
|
+
neutralizers: {
|
|
226
|
+
price: "$5. Less than a coffee. No risk.",
|
|
227
|
+
complexity: "Onboarding is a nuclear launch sequence. Fun, not scary.",
|
|
228
|
+
trust: "Show real things real people built. Screenshots, not promises.",
|
|
229
|
+
},
|
|
230
|
+
} as const;
|
|
231
|
+
|
|
232
|
+
// ===========================================================================
|
|
233
|
+
// EMOTIONAL ARC (what users should FEEL at each stage)
|
|
234
|
+
// ===========================================================================
|
|
235
|
+
|
|
236
|
+
export const emotionalArc = {
|
|
237
|
+
/** Landing page. First impression. */
|
|
238
|
+
landing: {
|
|
239
|
+
feel: "Holy shit, $5?",
|
|
240
|
+
job: "Widen the absurdity gap. Show power. Reveal price.",
|
|
241
|
+
tone: "Confident. Almost cocky. Like we know something you don't.",
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
/** Onboarding wizard. Signing up. */
|
|
245
|
+
onboarding: {
|
|
246
|
+
feel: "I'm launching a supercomputer.",
|
|
247
|
+
job: "Make it feel momentous. Nuclear launch codes. Mission briefing.",
|
|
248
|
+
tone: "Military command terminal. You're the operator.",
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
/** Dashboard. Daily driver. */
|
|
252
|
+
dashboard: {
|
|
253
|
+
feel: "It's actually running my business.",
|
|
254
|
+
job: "Show activity. Show things happening. The bot is ALIVE.",
|
|
255
|
+
tone: "Mission control. Calm competence. Everything is handled.",
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
/** Marketplace. Expanding capabilities. */
|
|
259
|
+
marketplace: {
|
|
260
|
+
feel: "I can make it do THAT too?",
|
|
261
|
+
job: "Show the possibilities. Make them want more. Candy store energy.",
|
|
262
|
+
tone: "Arsenal. Every plugin is a new superpower.",
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
/** Billing. Paying for it. */
|
|
266
|
+
billing: {
|
|
267
|
+
feel: "This costs nothing for what I'm getting.",
|
|
268
|
+
job: "Reinforce the absurdity gap. Show value vs cost.",
|
|
269
|
+
tone: "Transparent. Trustworthy. The numbers speak for themselves.",
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
/** Settings. Configuring. */
|
|
273
|
+
settings: {
|
|
274
|
+
feel: "I'm in control of a powerful machine.",
|
|
275
|
+
job: "Make configuration feel like tuning a race car, not filling forms.",
|
|
276
|
+
tone: "Control panel. Precise. Every toggle matters.",
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
/** Fleet health. Monitoring. */
|
|
280
|
+
fleet: {
|
|
281
|
+
feel: "My army is operational.",
|
|
282
|
+
job: "NORAD situation room. All systems nominal.",
|
|
283
|
+
tone: "Calm surveillance. Green means good. You're the general.",
|
|
284
|
+
},
|
|
285
|
+
} as const;
|
|
286
|
+
|
|
287
|
+
// ===========================================================================
|
|
288
|
+
// COLOR PALETTE
|
|
289
|
+
// ===========================================================================
|
|
290
|
+
|
|
291
|
+
export const colors = {
|
|
292
|
+
/** Pure black. The void. Default background. */
|
|
293
|
+
black: "#000000",
|
|
294
|
+
/** Terminal green. The primary brand color. Use for text, borders, accents. */
|
|
295
|
+
green: "#00FF41",
|
|
296
|
+
/** Dimmed green for secondary/muted elements. */
|
|
297
|
+
greenDim: "#00CC33",
|
|
298
|
+
/** Faint green for hover states and subtle backgrounds. */
|
|
299
|
+
greenFaint: "#00FF4110",
|
|
300
|
+
/** Green at 20% opacity for borders and dividers. */
|
|
301
|
+
greenBorder: "#00FF4133",
|
|
302
|
+
/** Pure white. Body text on dark backgrounds. */
|
|
303
|
+
white: "#FFFFFF",
|
|
304
|
+
/** Muted white for secondary text. */
|
|
305
|
+
gray: "#A0A0A0",
|
|
306
|
+
/** Dark gray for disabled/placeholder text. */
|
|
307
|
+
grayDim: "#666666",
|
|
308
|
+
/** Near-black for card/surface backgrounds. */
|
|
309
|
+
surface: "#0A0A0A",
|
|
310
|
+
/** Slightly lighter surface for elevated cards. */
|
|
311
|
+
surfaceElevated: "#111111",
|
|
312
|
+
/** Error/destructive red. Terminal-style. */
|
|
313
|
+
red: "#FF3333",
|
|
314
|
+
/** Warning amber. */
|
|
315
|
+
amber: "#FFAA00",
|
|
316
|
+
} as const;
|
|
317
|
+
|
|
318
|
+
// ===========================================================================
|
|
319
|
+
// TYPOGRAPHY
|
|
320
|
+
// ===========================================================================
|
|
321
|
+
|
|
322
|
+
export const typography = {
|
|
323
|
+
fontFamily: "'JetBrains Mono', monospace",
|
|
324
|
+
scale: {
|
|
325
|
+
/** Hero headline. One per viewport. */
|
|
326
|
+
hero: { size: "3rem", lineHeight: "1.1", weight: "700", tracking: "-0.02em" },
|
|
327
|
+
/** Page title. */
|
|
328
|
+
h1: { size: "2.25rem", lineHeight: "1.2", weight: "700", tracking: "-0.02em" },
|
|
329
|
+
/** Section heading. */
|
|
330
|
+
h2: { size: "1.5rem", lineHeight: "1.3", weight: "600", tracking: "-0.01em" },
|
|
331
|
+
/** Card heading. */
|
|
332
|
+
h3: { size: "1.125rem", lineHeight: "1.4", weight: "600", tracking: "0" },
|
|
333
|
+
/** Body text. */
|
|
334
|
+
body: { size: "1rem", lineHeight: "1.6", weight: "400", tracking: "0" },
|
|
335
|
+
/** Secondary/label text. */
|
|
336
|
+
small: { size: "0.875rem", lineHeight: "1.5", weight: "400", tracking: "0" },
|
|
337
|
+
/** Tiny text, badges, metadata. */
|
|
338
|
+
xs: { size: "0.75rem", lineHeight: "1.4", weight: "500", tracking: "0.02em" },
|
|
339
|
+
/** Code/terminal output. Same font, just used for semantic distinction. */
|
|
340
|
+
mono: { size: "0.875rem", lineHeight: "1.6", weight: "400", tracking: "0" },
|
|
341
|
+
},
|
|
342
|
+
} as const;
|
|
343
|
+
|
|
344
|
+
// ===========================================================================
|
|
345
|
+
// SPACING & LAYOUT
|
|
346
|
+
// ===========================================================================
|
|
347
|
+
|
|
348
|
+
export const layout = {
|
|
349
|
+
/** Maximum content width for marketing pages. */
|
|
350
|
+
maxWidth: "64rem",
|
|
351
|
+
/** One idea per viewport. Generous vertical rhythm. */
|
|
352
|
+
sectionPadding: "8rem",
|
|
353
|
+
/** Border radius: sharp, not rounded. Terminal aesthetic. */
|
|
354
|
+
radius: "0.25rem",
|
|
355
|
+
/** No radius at all. For inputs and terminal elements. */
|
|
356
|
+
radiusNone: "0",
|
|
357
|
+
} as const;
|
|
358
|
+
|
|
359
|
+
// ===========================================================================
|
|
360
|
+
// VOICE GUIDE
|
|
361
|
+
// ===========================================================================
|
|
362
|
+
|
|
363
|
+
export const voice = {
|
|
364
|
+
rules: [
|
|
365
|
+
"Short sentences. If it needs a comma, it needs two sentences.",
|
|
366
|
+
"No corporate language. Ever.",
|
|
367
|
+
"Confident, not humble.",
|
|
368
|
+
"The price is the punchline.",
|
|
369
|
+
"Show, don't list.",
|
|
370
|
+
"Internet-native. Write for screenshots and group chats.",
|
|
371
|
+
"Sell the outcome, not the tool.",
|
|
372
|
+
],
|
|
373
|
+
bannedWords: [
|
|
374
|
+
"leverage",
|
|
375
|
+
"empower",
|
|
376
|
+
"solution",
|
|
377
|
+
"unlock",
|
|
378
|
+
"seamless",
|
|
379
|
+
"robust",
|
|
380
|
+
"platform",
|
|
381
|
+
"synergy",
|
|
382
|
+
"paradigm",
|
|
383
|
+
"ecosystem",
|
|
384
|
+
"holistic",
|
|
385
|
+
"scalable",
|
|
386
|
+
"disrupt",
|
|
387
|
+
"innovate",
|
|
388
|
+
"democratize",
|
|
389
|
+
"next-gen",
|
|
390
|
+
"cutting-edge",
|
|
391
|
+
"game-changer",
|
|
392
|
+
],
|
|
393
|
+
notAllowed: [
|
|
394
|
+
"We're thrilled to announce...",
|
|
395
|
+
"We're excited to share...",
|
|
396
|
+
"Our powerful platform...",
|
|
397
|
+
"Seamless integration...",
|
|
398
|
+
"Leverage the power of...",
|
|
399
|
+
"Unlock your potential...",
|
|
400
|
+
"Empowering developers...",
|
|
401
|
+
"Robust and scalable...",
|
|
402
|
+
],
|
|
403
|
+
} as const;
|
|
404
|
+
|
|
405
|
+
// ===========================================================================
|
|
406
|
+
// DO / DON'T COPY EXAMPLES
|
|
407
|
+
// ===========================================================================
|
|
408
|
+
|
|
409
|
+
export function getCopyExamples() {
|
|
410
|
+
const name = productName();
|
|
411
|
+
const brand = brandName();
|
|
412
|
+
const domain = getBrandConfig().domain;
|
|
413
|
+
return [
|
|
414
|
+
// --- The supercomputer angle ---
|
|
415
|
+
{
|
|
416
|
+
do: "A supercomputer for $5/month.",
|
|
417
|
+
dont: "An affordable AI automation solution.",
|
|
418
|
+
rule: "Absurdity gap. Power vs price.",
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
do: `Your ${name} runs your business. You run your life.`,
|
|
422
|
+
dont: "Streamline your business operations with AI.",
|
|
423
|
+
rule: "Sell the outcome.",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
do: "Hire an army. Five dollars.",
|
|
427
|
+
dont: "Access our multi-agent orchestration system.",
|
|
428
|
+
rule: "Absurdity gap. The price is the punchline.",
|
|
429
|
+
},
|
|
430
|
+
// --- The $10K Mac Mini killer angle ---
|
|
431
|
+
{
|
|
432
|
+
do: "5 bots. $50/month. Do the math.",
|
|
433
|
+
dont: "Our cost-effective alternative to local hardware.",
|
|
434
|
+
rule: "Let them do the math. The contrast sells itself.",
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
do: "Skip the hardware. Keep the power.",
|
|
438
|
+
dont: "No expensive infrastructure required.",
|
|
439
|
+
rule: "Sell the outcome. Never say 'no X required.'",
|
|
440
|
+
},
|
|
441
|
+
// --- Product-name examples ---
|
|
442
|
+
{
|
|
443
|
+
do: `Get your ${name}.`,
|
|
444
|
+
dont: "Try our AI platform today.",
|
|
445
|
+
rule: "Confident, not humble.",
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
do: `Your ${name} runs while you sleep.`,
|
|
449
|
+
dont: "Our always-on solution ensures 24/7 uptime.",
|
|
450
|
+
rule: "Short sentences. No corporate language.",
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
do: "Build a company. $5/month.",
|
|
454
|
+
dont: "Leverage our powerful tools to unlock business potential.",
|
|
455
|
+
rule: "Sell the outcome. Price is the punchline.",
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
do: `${name} writes your code. Ships your product. Answers your DMs.`,
|
|
459
|
+
dont: `${brand} enables seamless automation across multiple workflows.`,
|
|
460
|
+
rule: "Show, don't list.",
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
do: `What would you do with your own ${name}?`,
|
|
464
|
+
dont: "Discover the possibilities of AI-powered automation.",
|
|
465
|
+
rule: "Sell the outcome, not the tool.",
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
do: `Your ${name}. Everything handled.`,
|
|
469
|
+
dont: "Our comprehensive solution covers all your needs.",
|
|
470
|
+
rule: "Short sentences.",
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
do: `Your ${name} doesn't take lunch breaks.`,
|
|
474
|
+
dont: "Benefit from continuous AI processing capabilities.",
|
|
475
|
+
rule: "Internet-native.",
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
do: "Replace yourself at your job. Keep the paycheck.",
|
|
479
|
+
dont: "Optimize your workflow with intelligent automation.",
|
|
480
|
+
rule: "Sell the outcome.",
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
do: `${name}. Not ${brand}. Not the ${brand} platform.`,
|
|
484
|
+
dont: `Powered by the ${brand} platform.`,
|
|
485
|
+
rule: `Product name is ${name}.`,
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
do: "Five bucks. Unlimited bots.",
|
|
489
|
+
dont: "Starting at just $5 per month with our flexible pricing.",
|
|
490
|
+
rule: "The price is the punchline.",
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
do: `Ship it. Your ${name} already did.`,
|
|
494
|
+
dont: "Accelerate your deployment pipeline with our robust tooling.",
|
|
495
|
+
rule: "Confident. No corporate language.",
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
do: domain,
|
|
499
|
+
dont: `Visit us at ${domain} to learn more about our offerings.`,
|
|
500
|
+
rule: "Internet-native. The URL is the noun.",
|
|
501
|
+
},
|
|
502
|
+
];
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/** @deprecated Use `getCopyExamples()` instead. */
|
|
506
|
+
export const copyExamples = getCopyExamples();
|
|
507
|
+
|
|
508
|
+
// ===========================================================================
|
|
509
|
+
// ANIMATION — TWO CONTEXTS
|
|
510
|
+
// ===========================================================================
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Animation rules differ between MARKETING pages and PRODUCT UI.
|
|
514
|
+
*
|
|
515
|
+
* Marketing: Extreme restraint. Let the copy do the work.
|
|
516
|
+
* Product UI: Functional motion. The supercomputer is alive.
|
|
517
|
+
*/
|
|
518
|
+
export const animation = {
|
|
519
|
+
/** Terminal typing effect speed in ms per character. */
|
|
520
|
+
typingSpeed: 50,
|
|
521
|
+
/** Cursor blink interval in ms. */
|
|
522
|
+
cursorBlink: 530,
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* MARKETING pages (landing, pricing, about).
|
|
526
|
+
* Restraint is what makes it feel expensive.
|
|
527
|
+
*/
|
|
528
|
+
marketing: {
|
|
529
|
+
allowed: ["typing-effect", "cursor-blink", "fade-in-on-scroll"],
|
|
530
|
+
banned: [
|
|
531
|
+
"parallax",
|
|
532
|
+
"floating-elements",
|
|
533
|
+
"scroll-jacking",
|
|
534
|
+
"hover-bounce",
|
|
535
|
+
"auto-playing-video",
|
|
536
|
+
],
|
|
537
|
+
philosophy: "Let the words land. One animation per viewport. The restraint IS the brand.",
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* PRODUCT UI (dashboard, settings, fleet, marketplace, onboarding).
|
|
542
|
+
* The supercomputer is alive. Motion = feedback. The UI breathes.
|
|
543
|
+
*/
|
|
544
|
+
productUI: {
|
|
545
|
+
allowed: [
|
|
546
|
+
"stagger-enter",
|
|
547
|
+
"fade-transition",
|
|
548
|
+
"status-pulse",
|
|
549
|
+
"count-up",
|
|
550
|
+
"skeleton-loading",
|
|
551
|
+
"hover-glow",
|
|
552
|
+
"selection-spring",
|
|
553
|
+
"page-fade",
|
|
554
|
+
"card-hover-lift",
|
|
555
|
+
"progress-fill",
|
|
556
|
+
"validation-shake",
|
|
557
|
+
"success-flash",
|
|
558
|
+
"slide-drawer",
|
|
559
|
+
],
|
|
560
|
+
banned: ["parallax", "scroll-jacking", "auto-playing-video", "bouncing-logos", "confetti"],
|
|
561
|
+
philosophy:
|
|
562
|
+
"Every animation is functional. Status pulses = alive. " +
|
|
563
|
+
"Stagger loads = data arriving. Hover glow = interactive. " +
|
|
564
|
+
"Nothing moves just to move. Motion is information.",
|
|
565
|
+
},
|
|
566
|
+
|
|
567
|
+
/** Backwards compat: the combined allowed/banned (union of both contexts). */
|
|
568
|
+
allowed: ["typing-effect", "cursor-blink"],
|
|
569
|
+
banned: ["parallax", "floating-elements", "scroll-jacking", "hover-bounce"],
|
|
570
|
+
} as const;
|
|
571
|
+
|
|
572
|
+
// ===========================================================================
|
|
573
|
+
// IMAGERY
|
|
574
|
+
// ===========================================================================
|
|
575
|
+
|
|
576
|
+
export const imagery = {
|
|
577
|
+
allowed: ["screenshots of real things people built", "terminal output", "code"],
|
|
578
|
+
banned: [
|
|
579
|
+
"stock photos",
|
|
580
|
+
"illustrations of diverse teams collaborating",
|
|
581
|
+
"abstract gradient blobs",
|
|
582
|
+
"generic tech imagery",
|
|
583
|
+
"AI-generated art",
|
|
584
|
+
],
|
|
585
|
+
} as const;
|
|
586
|
+
|
|
587
|
+
// ===========================================================================
|
|
588
|
+
// PAGE-LEVEL COPY FRAMEWORKS
|
|
589
|
+
// ===========================================================================
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Every page type has a copy framework. Use these to write headlines,
|
|
593
|
+
* subheads, and CTAs. Always reference emotionalArc for the target feeling.
|
|
594
|
+
*/
|
|
595
|
+
export function getCopyFrameworks() {
|
|
596
|
+
const name = productName();
|
|
597
|
+
return {
|
|
598
|
+
landing: {
|
|
599
|
+
headline: "Ask the question. Let imagination do the work.",
|
|
600
|
+
structure: "Question → Scenarios → Price reveal → CTA",
|
|
601
|
+
cta: `Get your ${name}`,
|
|
602
|
+
antiPattern: "Never list features. Show outcomes.",
|
|
603
|
+
example: {
|
|
604
|
+
headline: `What would you do with your own ${name}?`,
|
|
605
|
+
scenarios: [
|
|
606
|
+
"Run a company from your phone.",
|
|
607
|
+
"Ship code while you sleep.",
|
|
608
|
+
"Never answer a support ticket again.",
|
|
609
|
+
],
|
|
610
|
+
reveal: "$5/month. Not a typo.",
|
|
611
|
+
cta: `Get your ${name}`,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
|
|
615
|
+
onboarding: {
|
|
616
|
+
headline: "Mission briefing. You're the commander.",
|
|
617
|
+
structure: "Step label → Terminal-style instruction → Action",
|
|
618
|
+
cta: "Continue / Launch",
|
|
619
|
+
antiPattern: "Never say 'step 1 of 6.' Say 'STEP 01 // DESIGNATION.'",
|
|
620
|
+
tone: "Military command terminal. Every step is a mission phase.",
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
dashboard: {
|
|
624
|
+
headline: `Status report. Everything your ${name} did today.`,
|
|
625
|
+
structure: "Stats → Activity feed → Quick actions",
|
|
626
|
+
cta: `Launch another ${name}`,
|
|
627
|
+
antiPattern: "Never show an empty dashboard. Always show something happening.",
|
|
628
|
+
tone: "Mission control. Calm authority.",
|
|
629
|
+
},
|
|
630
|
+
|
|
631
|
+
marketplace: {
|
|
632
|
+
headline: `Make your ${name} do more.`,
|
|
633
|
+
structure: "Categories → Cards → Detail → Install",
|
|
634
|
+
cta: `Install / Add to your ${name}`,
|
|
635
|
+
antiPattern: "Never say 'browse our catalog.' This is an arsenal, not a library.",
|
|
636
|
+
tone: "Candy store meets armory.",
|
|
637
|
+
},
|
|
638
|
+
|
|
639
|
+
billing: {
|
|
640
|
+
headline: "What you're getting for $5.",
|
|
641
|
+
structure: "Balance → Usage breakdown → Top up",
|
|
642
|
+
cta: "Add credits",
|
|
643
|
+
antiPattern: "Never hide the price. Never make billing scary. Reinforce the deal.",
|
|
644
|
+
tone: "Transparent. The numbers are your friend.",
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
settings: {
|
|
648
|
+
headline: "Configure your supercomputer.",
|
|
649
|
+
structure: "Section → Form → Save confirmation",
|
|
650
|
+
cta: "Save",
|
|
651
|
+
antiPattern: "Never make settings feel like a chore. This is a control panel.",
|
|
652
|
+
tone: "Precise. Every toggle does something real.",
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
empty: {
|
|
656
|
+
headline: `Your ${name} could do more.`,
|
|
657
|
+
structure: "Terminal-style message → Suggestion → CTA",
|
|
658
|
+
antiPattern: "Never say 'nothing here yet.' Always suggest the next action.",
|
|
659
|
+
examples: [
|
|
660
|
+
`> NO CHANNELS LINKED. YOUR ${name.toUpperCase()} IS ISOLATED.`,
|
|
661
|
+
"> FLEET EMPTY. AWAITING LAUNCH ORDERS.",
|
|
662
|
+
`> NO PLUGINS INSTALLED. YOUR ${name.toUpperCase()} IS RUNNING STOCK.`,
|
|
663
|
+
],
|
|
664
|
+
},
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/** @deprecated Use `getCopyFrameworks()` instead. */
|
|
669
|
+
export const copyFrameworks = getCopyFrameworks();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { apiFetch } from "./api";
|
|
2
|
+
import type { ChangesetDetail } from "./changeset-types";
|
|
3
|
+
|
|
4
|
+
/** Fetch a single changeset by ID with full details. */
|
|
5
|
+
export async function getChangeset(id: string): Promise<ChangesetDetail> {
|
|
6
|
+
return apiFetch<ChangesetDetail>(`/v1/changesets/${encodeURIComponent(id)}`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Submit a review for a changeset. */
|
|
10
|
+
export async function submitChangesetReview(
|
|
11
|
+
id: string,
|
|
12
|
+
review: { status: "approved" | "rejected" | "changes_requested"; body?: string },
|
|
13
|
+
): Promise<unknown> {
|
|
14
|
+
return apiFetch<unknown>(`/v1/changesets/${encodeURIComponent(id)}/reviews`, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
body: JSON.stringify(review),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Post a comment on a changeset. */
|
|
21
|
+
export async function addChangesetComment(
|
|
22
|
+
id: string,
|
|
23
|
+
comment: { body: string; filePath?: string; lineNumber?: number },
|
|
24
|
+
): Promise<unknown> {
|
|
25
|
+
return apiFetch<unknown>(`/v1/changesets/${encodeURIComponent(id)}/comments`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
body: JSON.stringify(comment),
|
|
28
|
+
});
|
|
29
|
+
}
|