openship 0.1.0 → 0.1.1

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 (531) hide show
  1. package/.env.example +19 -3
  2. package/CONTRIBUTING.md +69 -19
  3. package/LICENSE +661 -0
  4. package/README.md +304 -108
  5. package/apps/api/Dockerfile +6 -8
  6. package/apps/api/package.json +25 -21
  7. package/apps/api/src/app.ts +46 -3
  8. package/apps/api/src/config/env.ts +81 -7
  9. package/apps/api/src/lib/auth-mode.ts +42 -0
  10. package/apps/api/src/lib/auth.ts +105 -0
  11. package/apps/api/src/lib/cache.ts +128 -0
  12. package/apps/api/src/lib/cloud-auth-proxy.ts +310 -0
  13. package/apps/api/src/lib/cloud-client.ts +103 -0
  14. package/apps/api/src/lib/compose-parser.ts +138 -0
  15. package/apps/api/src/lib/controller-helpers.ts +90 -0
  16. package/apps/api/src/lib/email-templates.ts +94 -0
  17. package/apps/api/src/lib/encryption.ts +102 -0
  18. package/apps/api/src/lib/local-user.ts +65 -0
  19. package/apps/api/src/lib/mail.ts +48 -0
  20. package/apps/api/src/lib/notifications.ts +195 -0
  21. package/apps/api/src/lib/openship-cloud.ts +101 -0
  22. package/apps/api/src/lib/resources.ts +96 -0
  23. package/apps/api/src/lib/screenshots.ts +189 -0
  24. package/apps/api/src/lib/ssh-manager.ts +369 -0
  25. package/apps/api/src/lib/ssl-scheduler.ts +109 -0
  26. package/apps/api/src/lib/stack-detector.ts +708 -0
  27. package/apps/api/src/lib/system-debug.ts +10 -0
  28. package/apps/api/src/middleware/auth.ts +49 -13
  29. package/apps/api/src/middleware/error-handler.ts +23 -3
  30. package/apps/api/src/middleware/index.ts +2 -0
  31. package/apps/api/src/middleware/internal-auth.ts +40 -0
  32. package/apps/api/src/middleware/local-only.ts +20 -0
  33. package/apps/api/src/middleware/rate-limiter.ts +9 -0
  34. package/apps/api/src/modules/analytics/analytics.controller.ts +111 -0
  35. package/apps/api/src/modules/analytics/analytics.routes.ts +29 -0
  36. package/apps/api/src/modules/analytics/analytics.schema.ts +37 -0
  37. package/apps/api/src/modules/analytics/analytics.service.ts +264 -0
  38. package/apps/api/src/modules/auth/auth.routes.ts +233 -6
  39. package/apps/api/src/modules/billing/billing.routes.ts +8 -0
  40. package/apps/api/src/modules/cloud/cloud.controller.ts +225 -0
  41. package/apps/api/src/modules/cloud/cloud.routes.ts +40 -0
  42. package/apps/api/src/modules/deployments/build.service.ts +791 -0
  43. package/apps/api/src/modules/deployments/deployment-lifecycle.ts +138 -0
  44. package/apps/api/src/modules/deployments/deployment.controller.ts +324 -16
  45. package/apps/api/src/modules/deployments/deployment.routes.ts +33 -7
  46. package/apps/api/src/modules/deployments/deployment.schema.ts +37 -5
  47. package/apps/api/src/modules/deployments/deployment.service.ts +178 -11
  48. package/apps/api/src/modules/deployments/preflight.ts +280 -0
  49. package/apps/api/src/modules/deployments/prepare.service.ts +252 -0
  50. package/apps/api/src/modules/deployments/session-manager.ts +283 -0
  51. package/apps/api/src/modules/deployments/ssl.service.ts +73 -0
  52. package/apps/api/src/modules/domains/domain.controller.ts +59 -7
  53. package/apps/api/src/modules/domains/domain.routes.ts +20 -5
  54. package/apps/api/src/modules/domains/domain.schema.ts +35 -0
  55. package/apps/api/src/modules/domains/domain.service.ts +375 -9
  56. package/apps/api/src/modules/github/github.auth.ts +397 -0
  57. package/apps/api/src/modules/github/github.controller.ts +387 -0
  58. package/apps/api/src/modules/github/github.local-auth.ts +251 -0
  59. package/apps/api/src/modules/github/github.routes.ts +50 -0
  60. package/apps/api/src/modules/github/github.schema.ts +52 -0
  61. package/apps/api/src/modules/github/github.service.ts +592 -0
  62. package/apps/api/src/modules/github/github.types.ts +158 -0
  63. package/apps/api/src/modules/github/github.webhook.ts +186 -0
  64. package/apps/api/src/modules/github/index.ts +16 -0
  65. package/apps/api/src/modules/health/health.routes.ts +35 -0
  66. package/apps/api/src/modules/projects/project.controller.ts +481 -12
  67. package/apps/api/src/modules/projects/project.routes.ts +63 -6
  68. package/apps/api/src/modules/projects/project.schema.ts +104 -6
  69. package/apps/api/src/modules/projects/project.service.ts +502 -11
  70. package/apps/api/src/modules/settings/settings.controller.ts +55 -0
  71. package/apps/api/src/modules/settings/settings.routes.ts +25 -0
  72. package/apps/api/src/modules/settings/settings.service.ts +49 -0
  73. package/apps/api/src/modules/system/filesystem.controller.ts +66 -0
  74. package/apps/api/src/modules/system/index.ts +1 -0
  75. package/apps/api/src/modules/system/server-check.controller.ts +475 -0
  76. package/apps/api/src/modules/system/setup-session.ts +255 -0
  77. package/apps/api/src/modules/system/setup.controller.ts +128 -0
  78. package/apps/api/src/modules/system/system.routes.ts +42 -0
  79. package/apps/api/src/modules/webhooks/webhook.controller.ts +57 -15
  80. package/apps/api/src/modules/webhooks/webhook.routes.ts +11 -8
  81. package/apps/api/src/modules/webhooks/webhook.service.ts +46 -5
  82. package/apps/api/src/modules/webhooks/webhook.types.ts +35 -0
  83. package/apps/api/tsconfig.json +3 -1
  84. package/apps/cli/package.json +8 -10
  85. package/apps/cli/tsconfig.json +2 -1
  86. package/apps/dashboard/Dockerfile +4 -6
  87. package/apps/dashboard/components.json +20 -0
  88. package/apps/dashboard/next-env.d.ts +6 -0
  89. package/apps/dashboard/next.config.mjs +11 -1
  90. package/apps/dashboard/package.json +25 -13
  91. package/apps/dashboard/postcss.config.mjs +5 -0
  92. package/apps/dashboard/public/android-chrome-192x192.png +0 -0
  93. package/apps/dashboard/public/android-chrome-512x512.png +0 -0
  94. package/apps/dashboard/public/apple-touch-icon.png +0 -0
  95. package/apps/dashboard/public/favicon-16x16.png +0 -0
  96. package/apps/dashboard/public/favicon-32x32.png +0 -0
  97. package/apps/dashboard/public/favicon.ico +0 -0
  98. package/apps/dashboard/public/site.webmanifest +19 -0
  99. package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +114 -0
  100. package/apps/dashboard/src/app/(auth)/layout.tsx +18 -3
  101. package/apps/dashboard/src/app/(auth)/login/page.tsx +215 -6
  102. package/apps/dashboard/src/app/(auth)/providers.tsx +34 -0
  103. package/apps/dashboard/src/app/(auth)/register/page.tsx +171 -5
  104. package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +172 -0
  105. package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +190 -0
  106. package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +162 -0
  107. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +166 -0
  108. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +119 -0
  109. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +291 -0
  110. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +71 -0
  111. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +270 -0
  112. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +87 -0
  113. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +169 -0
  114. package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +7 -0
  115. package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +1 -8
  116. package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +240 -0
  117. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +121 -0
  118. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +89 -0
  119. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +182 -0
  120. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +324 -0
  121. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +99 -0
  122. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +31 -0
  123. package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +101 -0
  124. package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +57 -0
  125. package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +109 -0
  126. package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +9 -0
  127. package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +9 -3
  128. package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +44 -0
  129. package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +176 -0
  130. package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +1 -6
  131. package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +321 -0
  132. package/apps/dashboard/src/app/(dashboard)/layout.tsx +22 -32
  133. package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +187 -0
  134. package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +147 -0
  135. package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +39 -0
  136. package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +548 -0
  137. package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +292 -0
  138. package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +36 -0
  139. package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +74 -0
  140. package/apps/dashboard/src/app/(dashboard)/library/page.tsx +121 -0
  141. package/apps/dashboard/src/app/(dashboard)/library/types.ts +26 -0
  142. package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +1 -6
  143. package/apps/dashboard/src/app/(dashboard)/page.tsx +485 -0
  144. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +22 -0
  145. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +286 -0
  146. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +235 -0
  147. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +174 -0
  148. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +45 -0
  149. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +95 -0
  150. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +11 -0
  151. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +523 -0
  152. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +246 -0
  153. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +93 -0
  154. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +261 -0
  155. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +391 -0
  156. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +133 -0
  157. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +95 -0
  158. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +62 -0
  159. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +333 -0
  160. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +66 -0
  161. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +27 -0
  162. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +134 -0
  163. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +25 -0
  164. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +159 -0
  165. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +58 -0
  166. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +170 -0
  167. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +33 -0
  168. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +56 -0
  169. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +157 -0
  170. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +14 -0
  171. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +52 -0
  172. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +249 -0
  173. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +682 -0
  174. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +127 -0
  175. package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +73 -0
  176. package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +330 -0
  177. package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +326 -4
  178. package/apps/dashboard/src/app/(dashboard)/providers.tsx +23 -0
  179. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +329 -0
  180. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +229 -0
  181. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +38 -0
  182. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +437 -0
  183. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +15 -0
  184. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +54 -0
  185. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +65 -0
  186. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +13 -0
  187. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +227 -0
  188. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +90 -0
  189. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +56 -0
  190. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +13 -0
  191. package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +666 -0
  192. package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +283 -0
  193. package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +110 -0
  194. package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +147 -0
  195. package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +54 -0
  196. package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +407 -0
  197. package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +32 -0
  198. package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +62 -3
  199. package/apps/dashboard/src/app/auth/callback/close/page.tsx +23 -0
  200. package/apps/dashboard/src/app/auth/callback/install/page.tsx +40 -0
  201. package/apps/dashboard/src/app/authorize/page.tsx +137 -0
  202. package/apps/dashboard/src/app/globals.css +57 -3
  203. package/apps/dashboard/src/app/layout.tsx +43 -3
  204. package/apps/dashboard/src/components/auth-shell.tsx +66 -0
  205. package/apps/dashboard/src/components/deployments/types.ts +44 -0
  206. package/apps/dashboard/src/components/global-deployments/index.ts +17 -0
  207. package/apps/dashboard/src/components/i18n-provider.tsx +100 -0
  208. package/apps/dashboard/src/components/import-project/BuildSettings.tsx +376 -0
  209. package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +161 -0
  210. package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +358 -0
  211. package/apps/dashboard/src/components/import-project/ComposeServices.tsx +455 -0
  212. package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +510 -0
  213. package/apps/dashboard/src/components/import-project/DockerSettings.tsx +64 -0
  214. package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +481 -0
  215. package/apps/dashboard/src/components/import-project/Frameworks.tsx +90 -0
  216. package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +160 -0
  217. package/apps/dashboard/src/components/import-project/types.ts +82 -0
  218. package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +173 -0
  219. package/apps/dashboard/src/components/language-switcher.tsx +36 -0
  220. package/apps/dashboard/src/components/logo.tsx +13 -0
  221. package/apps/dashboard/src/components/network-error-handler.tsx +27 -0
  222. package/apps/dashboard/src/components/oauth-buttons.tsx +81 -0
  223. package/apps/dashboard/src/components/overview/ActivityChart.tsx +247 -0
  224. package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +111 -0
  225. package/apps/dashboard/src/components/overview/CreditsCard.tsx +137 -0
  226. package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +195 -0
  227. package/apps/dashboard/src/components/overview/EmptyState.tsx +126 -0
  228. package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +92 -0
  229. package/apps/dashboard/src/components/overview/OverviewHeader.tsx +74 -0
  230. package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +344 -0
  231. package/apps/dashboard/src/components/overview/ProjectsCard.tsx +134 -0
  232. package/apps/dashboard/src/components/overview/QuickLinks.tsx +119 -0
  233. package/apps/dashboard/src/components/overview/SandboxesCard.tsx +150 -0
  234. package/apps/dashboard/src/components/overview/StatsGrid.tsx +166 -0
  235. package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +206 -0
  236. package/apps/dashboard/src/components/overview/UsageStats.tsx +79 -0
  237. package/apps/dashboard/src/components/overview/index.ts +30 -0
  238. package/apps/dashboard/src/components/overview/types.ts +116 -0
  239. package/apps/dashboard/src/components/page-header.tsx +25 -0
  240. package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +60 -0
  241. package/apps/dashboard/src/components/shared/AlertBox.tsx +39 -0
  242. package/apps/dashboard/src/components/shared/CTASection.tsx +45 -0
  243. package/apps/dashboard/src/components/shared/ErrorState.tsx +176 -0
  244. package/apps/dashboard/src/components/shared/FeatureCard.tsx +20 -0
  245. package/apps/dashboard/src/components/shared/MDXComponents.tsx +24 -0
  246. package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +286 -0
  247. package/apps/dashboard/src/components/shared/Modal.tsx +39 -0
  248. package/apps/dashboard/src/components/shared/OTPInput.tsx +122 -0
  249. package/apps/dashboard/src/components/shared/PageHero.tsx +21 -0
  250. package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +27 -0
  251. package/apps/dashboard/src/components/shared/StatCard.tsx +14 -0
  252. package/apps/dashboard/src/components/shared/ValueCard.tsx +20 -0
  253. package/apps/dashboard/src/components/shared/index.ts +8 -0
  254. package/apps/dashboard/src/components/sidebar.tsx +282 -0
  255. package/apps/dashboard/src/components/theme-provider.tsx +96 -0
  256. package/apps/dashboard/src/components/toast.tsx +106 -0
  257. package/apps/dashboard/src/components/ui/CustomCursor.tsx +107 -0
  258. package/apps/dashboard/src/components/ui/CustomSelect.tsx +126 -0
  259. package/apps/dashboard/src/components/ui/DropdownMenu.tsx +174 -0
  260. package/apps/dashboard/src/components/ui/FileIcon.jsx +59 -0
  261. package/apps/dashboard/src/components/ui/IconPickerModal.tsx +273 -0
  262. package/apps/dashboard/src/components/ui/InfoBanner.jsx +39 -0
  263. package/apps/dashboard/src/components/ui/Logo.tsx +14 -0
  264. package/apps/dashboard/src/components/ui/Modal.tsx +117 -0
  265. package/apps/dashboard/src/components/ui/PageContainer.tsx +12 -0
  266. package/apps/dashboard/src/components/ui/SectionContainer.jsx +7 -0
  267. package/apps/dashboard/src/components/ui/SlidingToggle.tsx +128 -0
  268. package/apps/dashboard/src/components/ui/Toast.tsx +29 -0
  269. package/apps/dashboard/src/components/ui/button.tsx +58 -0
  270. package/apps/dashboard/src/components/ui/card.tsx +60 -0
  271. package/apps/dashboard/src/components/ui/input.tsx +20 -0
  272. package/apps/dashboard/src/components/ui/label.tsx +19 -0
  273. package/apps/dashboard/src/components/ui/select.tsx +10 -0
  274. package/apps/dashboard/src/components/ui/textarea.tsx +9 -0
  275. package/apps/dashboard/src/constants/lang-colors.ts +25 -0
  276. package/apps/dashboard/src/constants/mock.ts +38 -0
  277. package/apps/dashboard/src/context/AuthContext.tsx +91 -0
  278. package/apps/dashboard/src/context/CloudContext.tsx +275 -0
  279. package/apps/dashboard/src/context/DeploymentContext.tsx +71 -0
  280. package/apps/dashboard/src/context/GitHubContext.tsx +288 -0
  281. package/apps/dashboard/src/context/ModalContext.tsx +300 -0
  282. package/apps/dashboard/src/context/NetworkContext.tsx +32 -0
  283. package/apps/dashboard/src/context/ProjectSettingsContext.tsx +727 -0
  284. package/apps/dashboard/src/context/ToastContext.tsx +129 -0
  285. package/apps/dashboard/src/context/deployment/index.ts +3 -0
  286. package/apps/dashboard/src/context/deployment/types.ts +183 -0
  287. package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +547 -0
  288. package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +176 -0
  289. package/apps/dashboard/src/hooks/useBuildConnection.ts +334 -0
  290. package/apps/dashboard/src/hooks/useMonitorStream.ts +146 -0
  291. package/apps/dashboard/src/hooks/useProjectData.ts +110 -0
  292. package/apps/dashboard/src/hooks/useSSEConnection.ts +465 -0
  293. package/apps/dashboard/src/hooks/useSSEStream.ts +309 -0
  294. package/apps/dashboard/src/hooks/useSessions.ts +104 -0
  295. package/apps/dashboard/src/hooks/useSetupStream.ts +223 -0
  296. package/apps/dashboard/src/i18n/dictionaries/ar.json +218 -0
  297. package/apps/dashboard/src/i18n/dictionaries/en.json +218 -0
  298. package/apps/dashboard/src/i18n/index.ts +16 -0
  299. package/apps/dashboard/src/lib/api/ai.ts +22 -0
  300. package/apps/dashboard/src/lib/api/auth.ts +13 -0
  301. package/apps/dashboard/src/lib/api/client.ts +199 -0
  302. package/apps/dashboard/src/lib/api/cloud.ts +15 -0
  303. package/apps/dashboard/src/lib/api/deploy.ts +58 -0
  304. package/apps/dashboard/src/lib/api/domains.ts +13 -0
  305. package/apps/dashboard/src/lib/api/endpoints.ts +129 -0
  306. package/apps/dashboard/src/lib/api/github.ts +31 -0
  307. package/apps/dashboard/src/lib/api/icons.ts +12 -0
  308. package/apps/dashboard/src/lib/api/index.ts +41 -0
  309. package/apps/dashboard/src/lib/api/projects.ts +153 -0
  310. package/apps/dashboard/src/lib/api/sandbox.ts +14 -0
  311. package/apps/dashboard/src/lib/api/settings.ts +21 -0
  312. package/apps/dashboard/src/lib/api/system.ts +159 -0
  313. package/apps/dashboard/src/lib/auth-client.ts +54 -0
  314. package/apps/dashboard/src/lib/country.ts +25 -0
  315. package/apps/dashboard/src/lib/server/api.ts +140 -0
  316. package/apps/dashboard/src/lib/server/session.ts +103 -0
  317. package/apps/dashboard/src/lib/sseClient.ts +241 -0
  318. package/apps/dashboard/src/lib/sseMessageProcessors.ts +323 -0
  319. package/apps/dashboard/src/lib/utils.ts +6 -0
  320. package/apps/dashboard/src/proxy.ts +46 -0
  321. package/apps/dashboard/src/styles/Toast.module.css +92 -0
  322. package/apps/dashboard/src/styles/fonts.css +93 -0
  323. package/apps/dashboard/src/styles/theme.css +336 -0
  324. package/apps/dashboard/src/types/research.ts +42 -0
  325. package/apps/dashboard/src/utils/SSEParser.js +150 -0
  326. package/apps/dashboard/src/utils/authWindow.ts +143 -0
  327. package/apps/dashboard/src/utils/codeTheme.ts +127 -0
  328. package/apps/dashboard/src/utils/colors.json +2810 -0
  329. package/apps/dashboard/src/utils/date.ts +121 -0
  330. package/apps/dashboard/src/utils/deployment.ts +128 -0
  331. package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +232 -0
  332. package/apps/dashboard/src/utils/extToLang.js +103 -0
  333. package/apps/dashboard/src/utils/github.ts +62 -0
  334. package/apps/dashboard/src/utils/icons.js +46 -0
  335. package/apps/dashboard/src/utils/repoSlug.ts +110 -0
  336. package/apps/dashboard/src/utils/research-api.ts +163 -0
  337. package/apps/dashboard/src/utils/suggestions.ts +84 -0
  338. package/apps/dashboard/src/utils/theme.js +1 -0
  339. package/apps/dashboard/src/utils/ui-helpers.tsx +30 -0
  340. package/apps/dashboard/src/utils/upload.js +12 -0
  341. package/apps/dashboard/tsconfig.json +27 -5
  342. package/apps/desktop/forge.config.json +36 -0
  343. package/apps/desktop/package.json +26 -0
  344. package/apps/desktop/scripts/dev.mjs +58 -0
  345. package/apps/desktop/src/main/index.ts +675 -0
  346. package/apps/desktop/src/main/types/desktop.d.ts +33 -0
  347. package/apps/desktop/src/preload/index.ts +88 -0
  348. package/apps/desktop/src/renderer/index.html +462 -0
  349. package/apps/desktop/src/renderer/onboarding.js +511 -0
  350. package/apps/desktop/src/renderer/styles.css +1139 -0
  351. package/apps/desktop/tsconfig.json +17 -0
  352. package/apps/web/.source/browser.ts +13 -0
  353. package/apps/web/.source/dynamic.ts +8 -0
  354. package/apps/web/.source/server.ts +22 -0
  355. package/apps/web/.source/source.config.mjs +20 -0
  356. package/apps/web/Dockerfile +4 -6
  357. package/apps/web/content/blog/how-ai-builds-work.mdx +55 -0
  358. package/apps/web/content/blog/introducing-openship.mdx +46 -0
  359. package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +59 -0
  360. package/apps/web/content/docs/_meta.json +14 -0
  361. package/apps/web/content/docs/api.mdx +98 -0
  362. package/apps/web/content/docs/cli.mdx +80 -0
  363. package/apps/web/content/docs/first-deployment.mdx +56 -0
  364. package/apps/web/content/docs/index.mdx +27 -0
  365. package/apps/web/content/docs/installation.mdx +65 -0
  366. package/apps/web/content/docs/quickstart.mdx +45 -0
  367. package/apps/web/next-env.d.ts +6 -0
  368. package/apps/web/next.config.mjs +16 -2
  369. package/apps/web/package.json +19 -12
  370. package/apps/web/postcss.config.mjs +5 -0
  371. package/apps/web/public/android-chrome-192x192.png +0 -0
  372. package/apps/web/public/android-chrome-512x512.png +0 -0
  373. package/apps/web/public/apple-touch-icon.png +0 -0
  374. package/apps/web/public/favicon-16x16.png +0 -0
  375. package/apps/web/public/favicon-32x32.png +0 -0
  376. package/apps/web/public/favicon.ico +0 -0
  377. package/apps/web/public/site.webmanifest +1 -0
  378. package/apps/web/source.config.ts +17 -0
  379. package/apps/web/src/app/(marketing)/layout.tsx +7 -22
  380. package/apps/web/src/app/blog/[...slug]/page.tsx +247 -0
  381. package/apps/web/src/app/blog/blog.css +575 -0
  382. package/apps/web/src/app/blog/layout.tsx +50 -0
  383. package/apps/web/src/app/blog/page.tsx +235 -0
  384. package/apps/web/src/app/docs/[[...slug]]/page.tsx +67 -0
  385. package/apps/web/src/app/docs/layout.tsx +62 -0
  386. package/apps/web/src/app/docs/toc-theme.css +71 -0
  387. package/apps/web/src/app/download/page.tsx +396 -0
  388. package/apps/web/src/app/globals.css +20 -3
  389. package/apps/web/src/app/layout.tsx +57 -3
  390. package/apps/web/src/app/page.tsx +47 -6
  391. package/apps/web/src/app/robots.ts +15 -0
  392. package/apps/web/src/app/sitemap.ts +35 -0
  393. package/apps/web/src/components/blog/share-sidebar.tsx +81 -0
  394. package/apps/web/src/components/blog/writer-sidebar.tsx +81 -0
  395. package/apps/web/src/components/landing/ai-native.tsx +169 -0
  396. package/apps/web/src/components/landing/backups.tsx +139 -0
  397. package/apps/web/src/components/landing/cdn.tsx +109 -0
  398. package/apps/web/src/components/landing/coming-soon.tsx +180 -0
  399. package/apps/web/src/components/landing/dark-section.tsx +166 -0
  400. package/apps/web/src/components/landing/dashboard.tsx +407 -0
  401. package/apps/web/src/components/landing/developer-experience.tsx +224 -0
  402. package/apps/web/src/components/landing/dns-domains.tsx +146 -0
  403. package/apps/web/src/components/landing/download-button.tsx +151 -0
  404. package/apps/web/src/components/landing/features/ai-visual.tsx +48 -0
  405. package/apps/web/src/components/landing/features/cloud-visual.tsx +44 -0
  406. package/apps/web/src/components/landing/features/git-visual.tsx +61 -0
  407. package/apps/web/src/components/landing/features/index.tsx +642 -0
  408. package/apps/web/src/components/landing/features/infra-visual.tsx +69 -0
  409. package/apps/web/src/components/landing/features/rollback-visual.tsx +42 -0
  410. package/apps/web/src/components/landing/features/ssl-visual.tsx +41 -0
  411. package/apps/web/src/components/landing/features/stacks-visual.tsx +54 -0
  412. package/apps/web/src/components/landing/final-cta.tsx +116 -0
  413. package/apps/web/src/components/landing/footer.tsx +145 -0
  414. package/apps/web/src/components/landing/hero.tsx +110 -0
  415. package/apps/web/src/components/landing/how-it-works.tsx +210 -0
  416. package/apps/web/src/components/landing/index.ts +21 -0
  417. package/apps/web/src/components/landing/mail-server.tsx +122 -0
  418. package/apps/web/src/components/landing/navbar.tsx +199 -0
  419. package/apps/web/src/components/landing/no-lockin.tsx +185 -0
  420. package/apps/web/src/components/landing/open-source-cta.tsx +151 -0
  421. package/apps/web/src/components/landing/portability.tsx +190 -0
  422. package/apps/web/src/components/landing/pricing.tsx +263 -0
  423. package/apps/web/src/components/landing/scaling.tsx +209 -0
  424. package/apps/web/src/components/landing/why-openship.tsx +291 -0
  425. package/apps/web/src/hooks/use-gsap-scroll.ts +158 -0
  426. package/apps/web/src/hooks/use-platform.ts +86 -0
  427. package/apps/web/src/lib/source.ts +12 -0
  428. package/apps/web/src/styles/fonts.css +84 -0
  429. package/apps/web/src/styles/landing.css +951 -0
  430. package/apps/web/src/styles/theme.css +227 -0
  431. package/apps/web/tsconfig.json +8 -3
  432. package/bun.lock +3260 -0
  433. package/docker-compose.yml +3 -0
  434. package/docs/screenshots/.gitkeep +0 -0
  435. package/docs/screenshots/screen.png +0 -0
  436. package/openship.code-workspace +7 -0
  437. package/package.json +23 -9
  438. package/packages/adapters/docs/ARCHITECTURE.md +160 -0
  439. package/packages/adapters/docs/BUILD-PIPELINE.md +171 -0
  440. package/packages/adapters/docs/CLOUD.md +239 -0
  441. package/packages/adapters/docs/EXECUTOR.md +174 -0
  442. package/packages/adapters/docs/LOG-STREAMING.md +175 -0
  443. package/packages/adapters/docs/SYSTEM.md +191 -0
  444. package/packages/adapters/package.json +14 -9
  445. package/packages/adapters/src/index.ts +144 -4
  446. package/packages/adapters/src/infra/cloud.ts +42 -0
  447. package/packages/adapters/src/infra/index.ts +9 -0
  448. package/packages/adapters/src/infra/noop.ts +27 -0
  449. package/packages/adapters/src/infra/traefik.ts +297 -0
  450. package/packages/adapters/src/infra/types.ts +36 -0
  451. package/packages/adapters/src/platform.ts +255 -0
  452. package/packages/adapters/src/runtime/bare.ts +567 -0
  453. package/packages/adapters/src/runtime/build-pipeline.ts +237 -0
  454. package/packages/adapters/src/runtime/cloud.ts +791 -0
  455. package/packages/adapters/src/runtime/deploy-pipeline.ts +146 -0
  456. package/packages/adapters/src/runtime/docker.ts +443 -0
  457. package/packages/adapters/src/runtime/index.ts +69 -0
  458. package/packages/adapters/src/runtime/local-build.ts +112 -0
  459. package/packages/adapters/src/runtime/transfer.ts +82 -0
  460. package/packages/adapters/src/runtime/types.ts +138 -0
  461. package/packages/adapters/src/system/catalog.ts +188 -0
  462. package/packages/adapters/src/system/checks.ts +228 -0
  463. package/packages/adapters/src/system/components.ts +45 -0
  464. package/packages/adapters/src/system/debug.ts +18 -0
  465. package/packages/adapters/src/system/environment.ts +168 -0
  466. package/packages/adapters/src/system/errors.ts +34 -0
  467. package/packages/adapters/src/system/executor.ts +600 -0
  468. package/packages/adapters/src/system/index.ts +58 -0
  469. package/packages/adapters/src/system/installer.ts +310 -0
  470. package/packages/adapters/src/system/setup.ts +442 -0
  471. package/packages/adapters/src/system/state.ts +96 -0
  472. package/packages/adapters/src/system/types.ts +116 -0
  473. package/packages/adapters/src/toolchain/catalog.ts +439 -0
  474. package/packages/adapters/src/toolchain/checks.ts +181 -0
  475. package/packages/adapters/src/toolchain/index.ts +38 -0
  476. package/packages/adapters/src/toolchain/installer.ts +189 -0
  477. package/packages/adapters/src/toolchain/types.ts +84 -0
  478. package/packages/adapters/src/types.ts +277 -0
  479. package/packages/adapters/tsconfig.json +3 -1
  480. package/packages/core/package.json +9 -9
  481. package/packages/core/src/constants.ts +44 -1
  482. package/packages/core/src/index.ts +2 -0
  483. package/packages/core/src/stacks.ts +778 -0
  484. package/packages/core/src/system.ts +111 -0
  485. package/packages/core/src/types.ts +22 -1
  486. package/packages/core/src/utils.ts +8 -0
  487. package/packages/core/tsconfig.json +3 -1
  488. package/packages/db/drizzle/0000_init.sql +231 -0
  489. package/packages/db/drizzle/0001_add_server_name.sql +1 -0
  490. package/packages/db/drizzle/meta/_journal.json +20 -0
  491. package/packages/db/drizzle.config.ts +10 -0
  492. package/packages/db/package.json +26 -14
  493. package/packages/db/src/client.ts +119 -0
  494. package/packages/db/src/index.ts +57 -8
  495. package/packages/db/src/repos/account.repo.ts +92 -0
  496. package/packages/db/src/repos/deployment.repo.ts +168 -0
  497. package/packages/db/src/repos/domain.repo.ts +102 -0
  498. package/packages/db/src/repos/git-installation.repo.ts +95 -0
  499. package/packages/db/src/repos/index.ts +43 -0
  500. package/packages/db/src/repos/instance-settings.repo.ts +43 -0
  501. package/packages/db/src/repos/project.repo.ts +159 -0
  502. package/packages/db/src/repos/session.repo.ts +82 -0
  503. package/packages/db/src/repos/settings.repo.ts +51 -0
  504. package/packages/db/src/repos/user.repo.ts +94 -0
  505. package/packages/db/src/schema/auth.ts +56 -0
  506. package/packages/db/src/schema/deployment.ts +87 -0
  507. package/packages/db/src/schema/domain.ts +46 -0
  508. package/packages/db/src/schema/github.ts +24 -0
  509. package/packages/db/src/schema/index.ts +6 -0
  510. package/packages/db/src/schema/project.ts +117 -0
  511. package/packages/db/src/schema/settings.ts +103 -0
  512. package/packages/db/tsconfig.json +3 -1
  513. package/packages/ui/package.json +17 -17
  514. package/packages/ui/src/components/status-dot.tsx +1 -1
  515. package/packages/ui/tsconfig.json +7 -2
  516. package/pnpm-workspace.yaml +0 -1
  517. package/{tooling/tsconfig/base.json → tsconfig.base.json} +0 -1
  518. package/turbo.json +4 -0
  519. package/apps/api/src/modules/auth/auth.controller.ts +0 -26
  520. package/apps/api/src/modules/auth/auth.schema.ts +0 -12
  521. package/apps/api/src/modules/auth/auth.service.ts +0 -23
  522. package/apps/dashboard/src/app/page.tsx +0 -6
  523. package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
  524. package/packages/adapters/src/base-adapter.ts +0 -49
  525. package/packages/adapters/src/docker-adapter.ts +0 -43
  526. package/packages/adapters/src/oblien-adapter.ts +0 -46
  527. package/packages/adapters/src/registry.ts +0 -22
  528. package/packages/db/prisma/schema.prisma +0 -160
  529. package/tooling/tsconfig/nextjs.json +0 -10
  530. package/tooling/tsconfig/node.json +0 -10
  531. package/tooling/tsconfig/package.json +0 -7
@@ -0,0 +1,291 @@
1
+ /* ── Why Openship — architectural advantages over alternatives ── */
2
+
3
+ const DIFFERENTIATORS = [
4
+ {
5
+ icon: (
6
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
7
+ <path strokeLinecap="round" strokeLinejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25A2.25 2.25 0 015.25 3h13.5A2.25 2.25 0 0121 5.25z" />
8
+ </svg>
9
+ ),
10
+ title: "Builds run locally by default",
11
+ desc: "Other tools build directly on your production server — eating CPU and RAM your apps need. Openship builds on your machine and only pushes production-ready containers. Need server-side builds for architecture compatibility? Toggle it on — you choose.",
12
+ highlight: "Your server stays fast — builds are offloaded",
13
+ color: "var(--th-clr-plum)",
14
+ bg: "var(--th-clr-plum-bg)",
15
+ blob: "var(--th-clr-plum-blob)",
16
+ },
17
+ {
18
+ icon: (
19
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
20
+ <path strokeLinecap="round" strokeLinejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
21
+ </svg>
22
+ ),
23
+ title: "Skip CI/CD. Click deploy.",
24
+ desc: "No pipelines to configure, no build servers to maintain, no YAML to write. Click deploy in the app — it builds, tests, and ships. When your team needs full CI/CD, it's there too.",
25
+ highlight: "CI/CD replaced by a button — available when you need it",
26
+ color: "var(--th-clr-sea)",
27
+ bg: "var(--th-clr-sea-bg)",
28
+ blob: "var(--th-clr-sea-blob)",
29
+ },
30
+ {
31
+ icon: (
32
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
33
+ <path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456z" />
34
+ </svg>
35
+ ),
36
+ title: "AI configures. You approve.",
37
+ desc: "Other tools still expect you to know Docker, NGINX, and reverse proxies. Openship's AI detects your stack, writes the config, sets up SSL, and deploys — you just confirm.",
38
+ highlight: "Zero infrastructure knowledge required",
39
+ color: "var(--th-clr-terra)",
40
+ bg: "var(--th-clr-terra-bg)",
41
+ blob: "var(--th-clr-terra-blob)",
42
+ },
43
+ {
44
+ icon: (
45
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
46
+ <path strokeLinecap="round" strokeLinejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3 0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7m0 0a3 3 0 01-3 3m0 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm-3 6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
47
+ </svg>
48
+ ),
49
+ title: "Nothing extra installed on your server",
50
+ desc: "Coolify and CapRover install a web dashboard, build system, and management layer on the server. Openship keeps your server clean — just your apps running in production. Works on any Linux box, VPS, or bare metal.",
51
+ highlight: "Lowest overhead of any deployment tool",
52
+ color: "var(--th-clr-plum)",
53
+ bg: "var(--th-clr-plum-bg)",
54
+ blob: "var(--th-clr-plum-blob)",
55
+ },
56
+ ];
57
+
58
+ /* ── Comparison table ── */
59
+ const COMPARE_ROWS: { feature: string; openship: string; others: string; win?: boolean }[] = [
60
+ { feature: "Where builds run", openship: "Local (or server when needed)", others: "Always on the server", win: true },
61
+ { feature: "Server overhead", openship: "Your apps only", others: "Dashboard + build system + DB", win: true },
62
+ { feature: "CI/CD", openship: "Built-in (or click to deploy)", others: "Configure pipelines & webhooks", win: true },
63
+ { feature: "Configuration", openship: "AI auto-detects & configures", others: "Manual YAML / Docker Compose", win: true },
64
+ { feature: "Deployment interface", openship: "Desktop app, web dashboard, or CLI", others: "Web dashboard on server", win: true },
65
+ { feature: "Server resources used for builds", openship: "0% by default", others: "Competes with production", win: true },
66
+ { feature: "Infrastructure knowledge", openship: "None required", others: "Docker, NGINX, SSH", win: true },
67
+ { feature: "Managed cloud option", openship: "Yes — fully managed", others: "Self-host only", win: true },
68
+ { feature: "Open source", openship: "MIT", others: "Varies (MIT / AGPL)", },
69
+ ];
70
+
71
+ export function WhyOpenship() {
72
+ return (
73
+ <section className="relative py-28 sm:py-36">
74
+ <div className="section-divider mx-auto mb-28 max-w-4xl sm:mb-36" />
75
+
76
+ <div className="mx-auto max-w-7xl px-6">
77
+ {/* ── Header ── */}
78
+ <div className="mx-auto max-w-3xl text-center">
79
+ <div className="mb-7 inline-flex items-center gap-2 rounded-full border border-[var(--th-on-06)] bg-white/60 px-4 py-1.5 shadow-[0_1px_3px_rgba(0,0,0,.04)] backdrop-blur-sm">
80
+ <span className="text-[12px] font-medium tracking-[0.02em] th-text-secondary">
81
+ Why Openship
82
+ </span>
83
+ </div>
84
+ <h2>
85
+ <span className="block text-[clamp(2.75rem,6vw,4.75rem)] font-semibold leading-[1.06] tracking-[-0.035em] th-text-heading">
86
+ Not another server tool.
87
+ </span>
88
+ <span
89
+ className="block text-[clamp(2.75rem,6vw,4.75rem)] font-semibold leading-[1.06] tracking-[-0.035em]"
90
+ style={{ color: "var(--th-on-40)" }}
91
+ >
92
+ A smarter architecture.
93
+ </span>
94
+ </h2>
95
+ <p className="mx-auto mt-6 max-w-xl text-[17px] leading-[1.65] th-text-body">
96
+ Coolify, CapRover, and Dokku all install on your server and build there too.
97
+ Openship builds locally by default — your server only runs production.
98
+ Need server-side builds? CI/CD? A web dashboard? It&apos;s all there.
99
+ Fully managed cloud or completely self-hosted — same platform, your call.
100
+ </p>
101
+ </div>
102
+
103
+ {/* ── Architecture diagram ── */}
104
+ <div className="mx-auto mt-16 max-w-4xl">
105
+ <div className="grid gap-4 sm:grid-cols-2">
106
+ {/* Other tools */}
107
+ <div className="rounded-2xl border border-[var(--th-card-bd)] bg-[var(--th-card-bg)] p-6 shadow-[var(--th-card-shadow)]">
108
+ <div className="mb-4 flex items-center gap-3">
109
+ <div
110
+ className="flex h-10 w-10 items-center justify-center rounded-xl"
111
+ style={{ background: "var(--th-clr-terra-bg)", color: "var(--th-clr-terra)" }}
112
+ >
113
+ <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
114
+ <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
115
+ </svg>
116
+ </div>
117
+ <div>
118
+ <p className="text-[14px] font-bold th-text-heading">Other self-hosting tools</p>
119
+ <p className="text-[12px] th-text-muted">Coolify · CapRover · Dokku</p>
120
+ </div>
121
+ </div>
122
+
123
+ <div className="space-y-2 rounded-xl border border-[var(--th-card-bd)] bg-[var(--th-sf-01)] p-4">
124
+ <p className="text-[11px] font-bold uppercase tracking-[0.08em] th-text-muted">Your server runs:</p>
125
+ <div className="space-y-1.5">
126
+ {[
127
+ "Management dashboard (web UI)",
128
+ "Build system (compiles your code)",
129
+ "CI/CD pipeline engine",
130
+ "Database for the tool itself",
131
+ "Reverse proxy config",
132
+ "Your actual apps",
133
+ ].map((item) => (
134
+ <div key={item} className="flex items-center gap-2 text-[13px]">
135
+ <span
136
+ className="h-1.5 w-1.5 rounded-full shrink-0"
137
+ style={{ background: "var(--th-clr-terra)" }}
138
+ />
139
+ <span className="th-text-body">{item}</span>
140
+ </div>
141
+ ))}
142
+ </div>
143
+ <p className="mt-3 rounded-lg px-3 py-2 text-[12px] font-medium" style={{ background: "var(--th-clr-terra-wash)", color: "var(--th-clr-terra)" }}>
144
+ Server resources split between builds and production
145
+ </p>
146
+ </div>
147
+ </div>
148
+
149
+ {/* Openship */}
150
+ <div className="rounded-2xl border border-[var(--th-card-bd)] bg-[var(--th-card-bg)] p-6 shadow-[var(--th-card-shadow)]">
151
+ <div className="mb-4 flex items-center gap-3">
152
+ <div
153
+ className="flex h-10 w-10 items-center justify-center rounded-xl"
154
+ style={{ background: "var(--th-clr-sea-bg)", color: "var(--th-clr-sea)" }}
155
+ >
156
+ <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
157
+ <path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
158
+ </svg>
159
+ </div>
160
+ <div>
161
+ <p className="text-[14px] font-bold th-text-heading">Openship</p>
162
+ <p className="text-[12px] th-text-muted">Flexible architecture</p>
163
+ </div>
164
+ </div>
165
+
166
+ <div className="space-y-3">
167
+ <div className="rounded-xl border border-[var(--th-card-bd)] bg-[var(--th-sf-01)] p-4">
168
+ <p className="text-[11px] font-bold uppercase tracking-[0.08em] th-text-muted">Your machine runs:</p>
169
+ <div className="mt-2 space-y-1.5">
170
+ {["Desktop app (UI + AI)", "Build system (compiles locally)", "Configuration engine"].map((item) => (
171
+ <div key={item} className="flex items-center gap-2 text-[13px]">
172
+ <span className="h-1.5 w-1.5 rounded-full shrink-0" style={{ background: "var(--th-clr-plum)" }} />
173
+ <span className="th-text-body">{item}</span>
174
+ </div>
175
+ ))}
176
+ </div>
177
+ </div>
178
+
179
+ <div className="flex items-center justify-center">
180
+ <svg className="h-5 w-5 th-text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
181
+ <path strokeLinecap="round" strokeLinejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" />
182
+ </svg>
183
+ <span className="ml-2 text-[11px] font-medium th-text-muted">Production containers only</span>
184
+ </div>
185
+
186
+ <div className="rounded-xl border border-[var(--th-card-bd)] bg-[var(--th-sf-01)] p-4">
187
+ <p className="text-[11px] font-bold uppercase tracking-[0.08em] th-text-muted">Your server runs:</p>
188
+ <div className="mt-2 space-y-1.5">
189
+ {["Your apps (production containers)", "Nothing else — no build system, no dashboard, no DB"].map((item) => (
190
+ <div key={item} className="flex items-center gap-2 text-[13px]">
191
+ <span className="h-1.5 w-1.5 rounded-full shrink-0" style={{ background: "var(--th-clr-sea)" }} />
192
+ <span className="th-text-body">{item}</span>
193
+ </div>
194
+ ))}
195
+ </div>
196
+ <p className="mt-3 rounded-lg px-3 py-2 text-[12px] font-medium" style={{ background: "var(--th-clr-sea-wash)", color: "var(--th-clr-sea)" }}>
197
+ 100% of server resources for your apps
198
+ </p>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </div>
204
+
205
+ {/* ── Differentiator cards ── */}
206
+ <div className="mx-auto mt-16 grid max-w-6xl gap-5 sm:grid-cols-2">
207
+ {DIFFERENTIATORS.map((d) => (
208
+ <div
209
+ key={d.title}
210
+ className="group relative overflow-hidden rounded-2xl border border-[var(--th-card-bd)] bg-[var(--th-card-bg)] p-7 shadow-[var(--th-card-shadow)] transition-colors hover:border-[var(--th-card-bd-hover)]"
211
+ >
212
+ {/* Ambient blob */}
213
+ <div
214
+ className="pointer-events-none absolute -right-12 -top-12 h-[160px] w-[160px] rounded-full blur-[60px] opacity-60"
215
+ style={{ background: d.blob }}
216
+ />
217
+
218
+ <div className="relative">
219
+ <div
220
+ className="mb-4 flex h-12 w-12 items-center justify-center rounded-xl"
221
+ style={{ background: d.bg, color: d.color }}
222
+ >
223
+ {d.icon}
224
+ </div>
225
+
226
+ <h3 className="text-[18px] font-bold leading-tight tracking-tight th-text-heading">
227
+ {d.title}
228
+ </h3>
229
+ <p className="mt-2.5 text-[14px] leading-[1.65] th-text-body">
230
+ {d.desc}
231
+ </p>
232
+ <p
233
+ className="mt-4 inline-block rounded-full px-3.5 py-1 text-[12px] font-semibold"
234
+ style={{ background: d.bg, color: d.color }}
235
+ >
236
+ {d.highlight}
237
+ </p>
238
+ </div>
239
+ </div>
240
+ ))}
241
+ </div>
242
+
243
+ {/* ── Comparison table ── */}
244
+ <div className="mx-auto mt-16 max-w-5xl overflow-hidden rounded-2xl border border-[var(--th-card-bd)] bg-[var(--th-card-bg)] shadow-[var(--th-card-shadow)]">
245
+ {/* Header row */}
246
+ <div className="grid grid-cols-[1fr_180px_180px] sm:grid-cols-[1fr_220px_220px] border-b-2 border-[var(--th-card-bd)] bg-[var(--th-sf-02)] px-6 py-4">
247
+ <span className="text-[13px] font-bold uppercase tracking-[0.08em] th-text-muted" />
248
+ <span className="text-center text-[14px] font-bold th-text-heading">
249
+ 🚀 Openship
250
+ </span>
251
+ <span className="text-center text-[14px] font-bold th-text-muted">
252
+ Others
253
+ </span>
254
+ </div>
255
+
256
+ {/* Data rows */}
257
+ {COMPARE_ROWS.map((r, i) => (
258
+ <div
259
+ key={r.feature}
260
+ className="grid grid-cols-[1fr_180px_180px] sm:grid-cols-[1fr_220px_220px] items-center border-t border-[var(--th-card-bd)] px-6 py-3.5"
261
+ style={{ background: i % 2 === 0 ? "transparent" : "var(--th-sf-01)" }}
262
+ >
263
+ <span className="text-[14px] font-medium th-text-heading">
264
+ {r.feature}
265
+ </span>
266
+ <span className="text-center">
267
+ <span
268
+ className="inline-block rounded-full px-3 py-0.5 text-[12px] font-semibold"
269
+ style={{ background: "var(--th-clr-sea-wash)", color: "var(--th-clr-sea)" }}
270
+ >
271
+ {r.openship}
272
+ </span>
273
+ </span>
274
+ <span className="text-center">
275
+ <span
276
+ className="inline-block rounded-full px-3 py-0.5 text-[12px] font-medium"
277
+ style={{
278
+ background: r.win ? "var(--th-clr-terra-wash)" : "var(--th-sf-04)",
279
+ color: r.win ? "var(--th-clr-terra)" : "var(--th-text-secondary)",
280
+ }}
281
+ >
282
+ {r.others}
283
+ </span>
284
+ </span>
285
+ </div>
286
+ ))}
287
+ </div>
288
+ </div>
289
+ </section>
290
+ );
291
+ }
@@ -0,0 +1,158 @@
1
+ "use client";
2
+
3
+ import { useEffect, useRef } from "react";
4
+ import gsap from "gsap";
5
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
6
+
7
+ gsap.registerPlugin(ScrollTrigger);
8
+
9
+ /**
10
+ * Scroll-linked GSAP animations with `scrub` for the features section.
11
+ *
12
+ * Progressive-enhancement pattern:
13
+ * 1. CSS: all elements visible by default (no opacity:0 in stylesheets).
14
+ * 2. JS adds `.feat-animated` class → CSS hides the targets (opacity:0).
15
+ * 3. `gsap.set()` applies initial transforms (y/x/scale).
16
+ * 4. `gsap.to()` + ScrollTrigger scrub reveals them on scroll.
17
+ * 5. If GSAP errors or the component unmounts, cleanup removes the class
18
+ * and reverts inline styles → elements are immediately visible again.
19
+ */
20
+ export function useGsapScroll() {
21
+ const containerRef = useRef<HTMLDivElement>(null);
22
+
23
+ useEffect(() => {
24
+ const el = containerRef.current;
25
+ if (!el) return;
26
+
27
+ /* Mark container so CSS can manage the "from" opacity */
28
+ el.classList.add("feat-animated");
29
+
30
+ let ctx: gsap.Context | undefined;
31
+
32
+ try {
33
+ ctx = gsap.context(() => {
34
+ /* ── Section header ─────────────────────────────── */
35
+ const header = el.querySelector<HTMLElement>(".feat-header");
36
+ if (header) {
37
+ gsap.set(header, { y: 60 });
38
+ gsap.to(header, {
39
+ y: 0,
40
+ opacity: 1,
41
+ ease: "none",
42
+ scrollTrigger: {
43
+ trigger: header,
44
+ start: "top 92%",
45
+ end: "top 60%",
46
+ scrub: 0.6,
47
+ },
48
+ });
49
+ }
50
+
51
+ /* ── Each feature card ──────────────────────────── */
52
+ const cards = el.querySelectorAll<HTMLElement>(".feat-card");
53
+
54
+ cards.forEach((card) => {
55
+ const text = card.querySelector<HTMLElement>(".feat-card-text");
56
+ const visual = card.querySelector<HTMLElement>(".feat-card-visual");
57
+ const buildItems = card.querySelectorAll<HTMLElement>(".feat-build-item");
58
+ const bullets = card.querySelectorAll<HTMLElement>(".feat-bullets li");
59
+ const inner = card.querySelector<HTMLElement>(".feat-card-inner");
60
+ const isReversed = inner?.classList.contains("feat-card-inner--reverse");
61
+
62
+ /* Card fade */
63
+ gsap.to(card, {
64
+ opacity: 1,
65
+ ease: "none",
66
+ scrollTrigger: {
67
+ trigger: card,
68
+ start: "top 90%",
69
+ end: "top 68%",
70
+ scrub: 0.6,
71
+ },
72
+ });
73
+
74
+ /* Text slides up */
75
+ if (text) {
76
+ gsap.set(text, { y: 44 });
77
+ gsap.to(text, {
78
+ y: 0,
79
+ opacity: 1,
80
+ ease: "none",
81
+ scrollTrigger: {
82
+ trigger: card,
83
+ start: "top 86%",
84
+ end: "top 56%",
85
+ scrub: 0.8,
86
+ },
87
+ });
88
+ }
89
+
90
+ /* Visual slides in from x-axis */
91
+ if (visual) {
92
+ const xFrom = isReversed ? -100 : 100;
93
+ gsap.set(visual, { x: xFrom });
94
+ gsap.to(visual, {
95
+ x: 0,
96
+ opacity: 1,
97
+ ease: "none",
98
+ scrollTrigger: {
99
+ trigger: card,
100
+ start: "top 88%",
101
+ end: "top 48%",
102
+ scrub: 1,
103
+ },
104
+ });
105
+ }
106
+
107
+ /* Build items — stagger in one-by-one */
108
+ if (buildItems.length) {
109
+ gsap.set(buildItems, { y: 20, scale: 0.97 });
110
+ gsap.to(buildItems, {
111
+ y: 0,
112
+ opacity: 1,
113
+ scale: 1,
114
+ stagger: 0.06,
115
+ ease: "none",
116
+ scrollTrigger: {
117
+ trigger: visual || card,
118
+ start: "top 72%",
119
+ end: "top 30%",
120
+ scrub: 0.9,
121
+ },
122
+ });
123
+ }
124
+
125
+ /* Bullet points */
126
+ if (bullets.length) {
127
+ gsap.set(bullets, { y: 18 });
128
+ gsap.to(bullets, {
129
+ y: 0,
130
+ opacity: 1,
131
+ stagger: 0.05,
132
+ ease: "none",
133
+ scrollTrigger: {
134
+ trigger: text || card,
135
+ start: "top 58%",
136
+ end: "top 32%",
137
+ scrub: 0.8,
138
+ },
139
+ });
140
+ }
141
+ });
142
+ }, el);
143
+
144
+ /* Force recalculate — handles pages loaded mid-scroll */
145
+ ScrollTrigger.refresh();
146
+ } catch {
147
+ /* GSAP failed → remove class so CSS shows everything */
148
+ el.classList.remove("feat-animated");
149
+ }
150
+
151
+ return () => {
152
+ el.classList.remove("feat-animated");
153
+ ctx?.revert();
154
+ };
155
+ }, []);
156
+
157
+ return containerRef;
158
+ }
@@ -0,0 +1,86 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+
5
+ export type Platform = "mac-arm" | "mac-intel" | "windows" | "linux" | "unknown";
6
+
7
+ export interface PlatformInfo {
8
+ platform: Platform;
9
+ label: string;
10
+ icon: "apple" | "windows" | "linux" | "download";
11
+ fileName: string;
12
+ }
13
+
14
+ const DOWNLOAD_BASE = "https://github.com/openshiporg/openship/releases/latest/download";
15
+
16
+ const PLATFORM_MAP: Record<Platform, PlatformInfo> = {
17
+ "mac-arm": {
18
+ platform: "mac-arm",
19
+ label: "Download for Mac",
20
+ icon: "apple",
21
+ fileName: "Openship-arm64.dmg",
22
+ },
23
+ "mac-intel": {
24
+ platform: "mac-intel",
25
+ label: "Download for Mac",
26
+ icon: "apple",
27
+ fileName: "Openship-x64.dmg",
28
+ },
29
+ windows: {
30
+ platform: "windows",
31
+ label: "Download for Windows",
32
+ icon: "windows",
33
+ fileName: "Openship-Setup.exe",
34
+ },
35
+ linux: {
36
+ platform: "linux",
37
+ label: "Download for Linux",
38
+ icon: "linux",
39
+ fileName: "Openship.AppImage",
40
+ },
41
+ unknown: {
42
+ platform: "unknown",
43
+ label: "Download",
44
+ icon: "download",
45
+ fileName: "",
46
+ },
47
+ };
48
+
49
+ function detectPlatform(): Platform {
50
+ if (typeof navigator === "undefined") return "unknown";
51
+
52
+ const ua = navigator.userAgent.toLowerCase();
53
+ const platform = (navigator as any).userAgentData?.platform?.toLowerCase() ?? navigator.platform?.toLowerCase() ?? "";
54
+
55
+ if (platform.includes("mac") || ua.includes("macintosh")) {
56
+ // Check for Apple Silicon
57
+ // Safari on Apple Silicon reports correctly, Chrome can use userAgentData
58
+ const isArm =
59
+ (navigator as any).userAgentData?.architecture === "arm" ||
60
+ // Heuristic: post-2020 Macs running modern browsers
61
+ (ua.includes("macintosh") && !ua.includes("intel"));
62
+ return isArm ? "mac-arm" : "mac-intel";
63
+ }
64
+
65
+ if (platform.includes("win") || ua.includes("windows")) return "windows";
66
+ if (platform.includes("linux") || ua.includes("linux")) return "linux";
67
+
68
+ return "unknown";
69
+ }
70
+
71
+ export function usePlatform() {
72
+ const [info, setInfo] = useState<PlatformInfo>(PLATFORM_MAP.unknown);
73
+
74
+ useEffect(() => {
75
+ const detected = detectPlatform();
76
+ setInfo(PLATFORM_MAP[detected]);
77
+ }, []);
78
+
79
+ return {
80
+ ...info,
81
+ downloadUrl: info.fileName ? `${DOWNLOAD_BASE}/${info.fileName}` : "/download",
82
+ allPlatforms: Object.values(PLATFORM_MAP).filter((p) => p.platform !== "unknown"),
83
+ getDownloadUrl: (p: Platform) =>
84
+ `${DOWNLOAD_BASE}/${PLATFORM_MAP[p].fileName}`,
85
+ };
86
+ }
@@ -0,0 +1,12 @@
1
+ import { docs, blog } from "@/.source/server";
2
+ import { loader } from "fumadocs-core/source";
3
+
4
+ export const docsSource = loader({
5
+ baseUrl: "/docs",
6
+ source: docs.toFumadocsSource(),
7
+ });
8
+
9
+ export const blogSource = loader({
10
+ baseUrl: "/blog",
11
+ source: blog.toFumadocsSource(),
12
+ });
@@ -0,0 +1,84 @@
1
+ /*
2
+ * ─────────────────────────────────────────────────────────────────
3
+ * OPENSHIP FONTS
4
+ * Gellix (Latin) + SF Arabic (RTL fallback)
5
+ * Imported once via globals.css
6
+ * ─────────────────────────────────────────────────────────────────
7
+ */
8
+
9
+ /* ── Gellix ───────────────────────────────────────────────────── */
10
+
11
+ @font-face {
12
+ font-family: 'Gellix';
13
+ src: url('https://cdn.oblien.com/fonts/Gellix-Thin.woff2') format('woff2');
14
+ font-weight: 100;
15
+ font-style: normal;
16
+ font-display: swap;
17
+ }
18
+
19
+ @font-face {
20
+ font-family: 'Gellix';
21
+ src: url('https://cdn.oblien.com/fonts/Gellix-Light.woff2') format('woff2');
22
+ font-weight: 300;
23
+ font-style: normal;
24
+ font-display: swap;
25
+ }
26
+
27
+ @font-face {
28
+ font-family: 'Gellix';
29
+ src: url('https://cdn.oblien.com/fonts/Gellix-Regular.woff2') format('woff2');
30
+ font-weight: 400;
31
+ font-style: normal;
32
+ font-display: swap;
33
+ }
34
+
35
+ @font-face {
36
+ font-family: 'Gellix';
37
+ src: url('https://cdn.oblien.com/fonts/Gellix-Medium.woff2') format('woff2');
38
+ font-weight: 500;
39
+ font-style: normal;
40
+ font-display: swap;
41
+ }
42
+
43
+ @font-face {
44
+ font-family: 'Gellix';
45
+ src: url('https://cdn.oblien.com/fonts/Gellix-SemiBold.woff2') format('woff2');
46
+ font-weight: 600;
47
+ font-style: normal;
48
+ font-display: swap;
49
+ }
50
+
51
+ @font-face {
52
+ font-family: 'Gellix';
53
+ src: url('https://cdn.oblien.com/fonts/Gellix-Bold.woff2') format('woff2');
54
+ font-weight: 700;
55
+ font-style: normal;
56
+ font-display: swap;
57
+ }
58
+
59
+ @font-face {
60
+ font-family: 'Gellix';
61
+ src: url('https://cdn.oblien.com/fonts/Gellix-ExtraBold.woff2') format('woff2');
62
+ font-weight: 800;
63
+ font-style: normal;
64
+ font-display: swap;
65
+ }
66
+
67
+ @font-face {
68
+ font-family: 'Gellix';
69
+ src: url('https://cdn.oblien.com/fonts/Gellix-Black.woff2') format('woff2');
70
+ font-weight: 900;
71
+ font-style: normal;
72
+ font-display: swap;
73
+ }
74
+
75
+ /* ── SF Arabic ────────────────────────────────────────────────── */
76
+
77
+ @font-face {
78
+ font-family: 'SF Arabic';
79
+ src: local('SF Arabic'), local('SFArabic-Regular'),
80
+ url('https://cdn.oblien.com/fonts/SFArabic-Regular.ttf') format('truetype');
81
+ font-weight: normal;
82
+ font-style: normal;
83
+ font-display: swap;
84
+ }