| 1 | import type { Metadata } from "next"; |
| 2 | import { allPosts } from "contentlayer/generated"; |
| 3 | import Link from "next/link"; |
| 4 | import TabbedRunner from "./components/TabbedRunner"; |
| 5 | import { FaApple, FaGooglePlay, FaWindows } from "react-icons/fa"; |
| 6 | import { StructuredData } from "@/components/structured-data"; |
| 7 | import siteMetadata from "@/content/siteMetadata"; |
| 8 | import { absoluteUrl, genPageMetadata } from "./seo"; |
| 9 | import { FrameworkWordCycler } from "@/components/word-cycler"; |
| 10 | |
| 11 | const proofPoints = [ |
| 12 | { |
| 13 | title: "One command", |
| 14 | description: "Run `smb` to deploy.", |
| 15 | }, |
| 16 | { |
| 17 | title: "SSH-first", |
| 18 | description: "No extra layer between you and the server.", |
| 19 | }, |
| 20 | { |
| 21 | title: "Live logs", |
| 22 | description: "Watch the deploy as it happens.", |
| 23 | }, |
| 24 | { |
| 25 | title: "Fast rollbacks", |
| 26 | description: "One command back when something breaks.", |
| 27 | }, |
| 28 | ]; |
| 29 | |
| 30 | const reasonsToChoose = [ |
| 31 | { |
| 32 | title: "No platform maze", |
| 33 | description: "Run `smb`, watch the release, move on.", |
| 34 | }, |
| 35 | { |
| 36 | title: "Built for real stacks", |
| 37 | description: "Node.js, Rails, and Vapor. That's it.", |
| 38 | }, |
| 39 | { |
| 40 | title: "Closer to normal ops", |
| 41 | description: "SSH in, deploy out. Nothing new to learn.", |
| 42 | }, |
| 43 | ]; |
| 44 | |
| 45 | const bestFit = [ |
| 46 | "Small teams shipping web apps and APIs", |
| 47 | "Agencies managing client deployments", |
| 48 | "Founders who want deploys to be boring", |
| 49 | "Teams that like SSH and fewer moving parts", |
| 50 | ]; |
| 51 | |
| 52 | const featuredServices = [ |
| 53 | { |
| 54 | name: "smbCloud Auth", |
| 55 | eyebrow: "Accounts and access", |
| 56 | title: "Hosted auth that stays out of the way.", |
| 57 | description: |
| 58 | "Handle sign-in, signup, sessions, custom domains, collaborators, and billing without adopting a giant identity platform first.", |
| 59 | bullets: [ |
| 60 | "Hosted auth apps for end-user accounts", |
| 61 | "Simple plans from Starter to Business", |
| 62 | "A calmer alternative to Auth0, Clerk, and bundled platform auth", |
| 63 | ], |
| 64 | href: "/auth", |
| 65 | cta: "Explore Auth", |
| 66 | accent: "indigo", |
| 67 | }, |
| 68 | { |
| 69 | name: "smbCloud Mail", |
| 70 | eyebrow: "Domain mail routing", |
| 71 | title: "Mail built around the inbox, not just the send API.", |
| 72 | description: |
| 73 | "Route domain email, keep forwarding simple, and store inbound history without stitching together a bigger mail suite than you need.", |
| 74 | bullets: [ |
| 75 | "One Mail app per project", |
| 76 | "Inbox routes, forwarding, and stored inbound messages", |
| 77 | "A cleaner fit for teams comparing Resend, useSend, or SendGrid", |
| 78 | ], |
| 79 | href: "/mail", |
| 80 | cta: "Explore Mail", |
| 81 | accent: "orange", |
| 82 | }, |
| 83 | ]; |
| 84 | |
| 85 | const deployComparisonPages = [ |
| 86 | { |
| 87 | href: "/heroku-alternative", |
| 88 | eyebrow: "Deploy comparison", |
| 89 | title: "Heroku alternative", |
| 90 | description: "Simpler deploys, less platform in the middle.", |
| 91 | bullets: [ |
| 92 | "Why some Rails, Node.js, and Vapor teams leave Heroku", |
| 93 | "Where smbCloud fits, and where it does not", |
| 94 | ], |
| 95 | }, |
| 96 | { |
| 97 | href: "/railway-alternative", |
| 98 | eyebrow: "Deploy comparison", |
| 99 | title: "Railway alternative", |
| 100 | description: "A calmer deploy flow for teams that want less surface area.", |
| 101 | bullets: [ |
| 102 | "What you gain from a narrower platform", |
| 103 | "Why some teams prefer less surface area", |
| 104 | ], |
| 105 | }, |
| 106 | ]; |
| 107 | |
| 108 | const authComparisonPages = [ |
| 109 | { |
| 110 | href: "/auth0-alternative", |
| 111 | eyebrow: "Auth comparison", |
| 112 | title: "Auth0 alternative", |
| 113 | description: "Hosted auth without the identity platform overhead.", |
| 114 | bullets: [ |
| 115 | "Compare hosted sign-in, signup, and session flows against a bigger identity stack", |
| 116 | "See where smbCloud Auth fits for smaller teams that want less auth sprawl", |
| 117 | ], |
| 118 | }, |
| 119 | { |
| 120 | href: "/clerk-alternative", |
| 121 | eyebrow: "Auth comparison", |
| 122 | title: "Clerk alternative", |
| 123 | description: "Auth that stays out of the way.", |
| 124 | bullets: [ |
| 125 | "Compare developer-friendly hosted auth against a calmer auth workflow", |
| 126 | "See when smbCloud Auth is a better fit and when Clerk still makes more sense", |
| 127 | ], |
| 128 | }, |
| 129 | ]; |
| 130 | |
| 131 | const gresiqComparisonPages = [ |
| 132 | { |
| 133 | href: "/supabase-alternative", |
| 134 | eyebrow: "GresIQ comparison", |
| 135 | title: "Supabase alternative", |
| 136 | description: "A data layer that doesn't become its own platform.", |
| 137 | bullets: [ |
| 138 | "Compare focused database management against a full BaaS platform", |
| 139 | "See when smbCloud GresIQ is the simpler fit and when Supabase still makes sense", |
| 140 | ], |
| 141 | }, |
| 142 | { |
| 143 | href: "/planetscale-alternative", |
| 144 | eyebrow: "GresIQ comparison", |
| 145 | title: "PlanetScale alternative", |
| 146 | description: |
| 147 | "A database that ships with your app, no branching workflow required.", |
| 148 | bullets: [ |
| 149 | "Compare database-per-project workflows against branch-based schema management", |
| 150 | "Honest tradeoffs between simplicity and scale", |
| 151 | ], |
| 152 | }, |
| 153 | { |
| 154 | href: "/neon-alternative", |
| 155 | eyebrow: "GresIQ comparison", |
| 156 | title: "Neon alternative", |
| 157 | description: |
| 158 | "Always-on Postgres without cold starts or serverless trade-offs.", |
| 159 | bullets: [ |
| 160 | "Compare always-on managed databases against serverless Postgres", |
| 161 | "See which fits better for teams that already use smbCloud Deploy or Auth", |
| 162 | ], |
| 163 | }, |
| 164 | ]; |
| 165 | |
| 166 | const mailComparisonPages = [ |
| 167 | { |
| 168 | href: "/resend-alternative", |
| 169 | eyebrow: "Mail comparison", |
| 170 | title: "Resend alternative", |
| 171 | description: "Starts with the inbox, not the send API.", |
| 172 | bullets: [ |
| 173 | "Compare inbox-first mail workflows against sending-first tools", |
| 174 | "See where smbCloud Mail fits for routing, forwarding, and stored inbound mail", |
| 175 | ], |
| 176 | }, |
| 177 | { |
| 178 | href: "/usesend-alternative", |
| 179 | eyebrow: "Mail comparison", |
| 180 | title: "useSend alternative", |
| 181 | description: "Managed mail without running the stack yourself.", |
| 182 | bullets: [ |
| 183 | "A cleaner fit for domain inbox routes and forwarding", |
| 184 | "Honest tradeoffs between hosted mail and open-source sending infrastructure", |
| 185 | ], |
| 186 | }, |
| 187 | { |
| 188 | href: "/sendgrid-alternative", |
| 189 | eyebrow: "Mail comparison", |
| 190 | title: "SendGrid alternative", |
| 191 | description: "Domain inboxes and inbound routing without the giant suite.", |
| 192 | bullets: [ |
| 193 | "Compare inbox routes, forwarding, and stored inbound mail against send-heavy tooling", |
| 194 | "See when smbCloud Mail is the better bet and when it is not", |
| 195 | ], |
| 196 | }, |
| 197 | ]; |
| 198 | |
| 199 | export const metadata: Metadata = { |
| 200 | ...genPageMetadata({ |
| 201 | title: "Deploy, Auth, Mail, and GresIQ on one platform", |
| 202 | description: |
| 203 | "smbCloud Platform brings four services together: ship Node.js, Rails, and Vapor apps with Deploy, handle sign-in and accounts with Auth, route domain email with Mail, and run your database with GresIQ.", |
| 204 | path: "/", |
| 205 | keywords: [ |
| 206 | "smbCloud Platform", |
| 207 | "SSH-first deploy platform", |
| 208 | "deploy Node.js app", |
| 209 | "deploy Ruby on Rails app", |
| 210 | "deploy Vapor app", |
| 211 | "hosted auth", |
| 212 | "authentication service", |
| 213 | "domain mail routing", |
| 214 | "managed Postgres database", |
| 215 | "Heroku alternative", |
| 216 | "Auth0 alternative", |
| 217 | "Resend alternative", |
| 218 | "small team deployment platform", |
| 219 | ], |
| 220 | }), |
| 221 | }; |
| 222 | |
| 223 | const homepageStructuredData = { |
| 224 | "@context": "https://schema.org", |
| 225 | "@graph": [ |
| 226 | { |
| 227 | "@type": "WebPage", |
| 228 | "@id": absoluteUrl("/#webpage"), |
| 229 | url: absoluteUrl("/"), |
| 230 | name: "smbCloud homepage", |
| 231 | description: siteMetadata.description, |
| 232 | isPartOf: { |
| 233 | "@id": absoluteUrl("/#website"), |
| 234 | }, |
| 235 | about: { |
| 236 | "@id": absoluteUrl("/#organization"), |
| 237 | }, |
| 238 | }, |
| 239 | { |
| 240 | "@type": "Service", |
| 241 | name: "smbCloud Deploy", |
| 242 | serviceType: "SSH-first application deployment platform", |
| 243 | provider: { |
| 244 | "@id": absoluteUrl("/#organization"), |
| 245 | }, |
| 246 | areaServed: "Worldwide", |
| 247 | url: absoluteUrl("/"), |
| 248 | description: |
| 249 | "Deploy Node.js, Ruby on Rails, and Swift/Vapor apps with one command, live logs, and fast rollbacks.", |
| 250 | audience: { |
| 251 | "@type": "Audience", |
| 252 | audienceType: "Developers and small software teams", |
| 253 | }, |
| 254 | }, |
| 255 | { |
| 256 | "@type": "Service", |
| 257 | name: "smbCloud Auth", |
| 258 | serviceType: "Hosted authentication service", |
| 259 | provider: { |
| 260 | "@id": absoluteUrl("/#organization"), |
| 261 | }, |
| 262 | areaServed: "Worldwide", |
| 263 | url: absoluteUrl("/auth"), |
| 264 | description: |
| 265 | "Hosted auth apps for sign-in, signup, sessions, collaborators, and account management.", |
| 266 | audience: { |
| 267 | "@type": "Audience", |
| 268 | audienceType: "Developers and software teams shipping user accounts", |
| 269 | }, |
| 270 | }, |
| 271 | { |
| 272 | "@type": "Service", |
| 273 | name: "smbCloud Mail", |
| 274 | serviceType: "Domain mail routing service", |
| 275 | provider: { |
| 276 | "@id": absoluteUrl("/#organization"), |
| 277 | }, |
| 278 | areaServed: "Worldwide", |
| 279 | url: absoluteUrl("/mail"), |
| 280 | description: |
| 281 | "Domain inbox routes, forwarding, and stored inbound mail for teams that want calmer mail infrastructure.", |
| 282 | audience: { |
| 283 | "@type": "Audience", |
| 284 | audienceType: |
| 285 | "Businesses and software teams handling inbound domain email", |
| 286 | }, |
| 287 | }, |
| 288 | ], |
| 289 | }; |
| 290 | |
| 291 | export default function Home() { |
| 292 | let publishedPosts = allPosts.filter((post) => post.published); |
| 293 | publishedPosts = publishedPosts.sort( |
| 294 | (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime(), |
| 295 | ); |
| 296 | |
| 297 | return ( |
| 298 | <div> |
| 299 | <StructuredData data={homepageStructuredData} /> |
| 300 | |
| 301 | <section className="relative overflow-hidden px-6 pt-24 pb-20 sm:pt-36 sm:pb-28 lg:px-8"> |
| 302 | <div className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-[600px] bg-[radial-gradient(ellipse_80%_50%_at_50%_0%,rgba(99,102,241,0.18),transparent)] dark:bg-[radial-gradient(ellipse_80%_50%_at_50%_0%,rgba(99,102,241,0.12),transparent)]" /> |
| 303 | |
| 304 | <div className="mx-auto max-w-4xl text-center"> |
| 305 | <p className="mb-8 text-sm font-semibold uppercase tracking-[0.2em] text-slate-500 dark:text-slate-500"> |
| 306 | Start at the finish line: distribution. |
| 307 | </p> |
| 308 | |
| 309 | <h1 className="text-5xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-7xl leading-[1.05]"> |
| 310 | Enterprise power at{" "} |
| 311 | <span className="text-indigo-600 dark:text-indigo-400"> |
| 312 | startup velocity |
| 313 | </span> |
| 314 | . |
| 315 | </h1> |
| 316 | |
| 317 | <p className="mx-auto mt-8 max-w-2xl text-lg leading-8 text-slate-600 dark:text-slate-400"> |
| 318 | smbCloud Platform brings Deploy, Auth, Mail, and GresIQ together. Ship |
| 319 | your <FrameworkWordCycler /> app without running four separate |
| 320 | vendors. |
| 321 | </p> |
| 322 | |
| 323 | <div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row"> |
| 324 | <Link |
| 325 | href="https://console.smbcloud.xyz" |
| 326 | target="_blank" |
| 327 | rel="noopener noreferrer" |
| 328 | className="w-full rounded-lg bg-indigo-600 px-8 py-3.5 text-sm font-semibold text-white shadow-lg shadow-indigo-500/20 transition-all hover:bg-indigo-500 hover:shadow-indigo-500/30 active:scale-[0.98] sm:w-auto" |
| 329 | > |
| 330 | Start free → |
| 331 | </Link> |
| 332 | <Link |
| 333 | href="/services" |
| 334 | className="inline-flex w-full items-center justify-center rounded-lg border border-slate-300 dark:border-white/[0.12] px-8 py-3.5 text-sm font-semibold text-slate-700 dark:text-slate-200 transition-colors hover:bg-slate-50 dark:hover:bg-white/[0.04] sm:w-auto" |
| 335 | > |
| 336 | Explore the platform |
| 337 | </Link> |
| 338 | </div> |
| 339 | </div> |
| 340 | </section> |
| 341 | |
| 342 | <section className="px-6 pb-14 lg:px-8"> |
| 343 | <div className="mx-auto max-w-5xl"> |
| 344 | <div className="mb-10 max-w-3xl"> |
| 345 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 346 | Start here |
| 347 | </p> |
| 348 | <h2 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-4xl"> |
| 349 | Auth and Mail are two of the clearest ways into smbCloud. |
| 350 | </h2> |
| 351 | <p className="mt-5 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 352 | If you're comparing auth vendors or trying to clean up your domain |
| 353 | mail setup, start with the product page that matches the job. |
| 354 | </p> |
| 355 | </div> |
| 356 | |
| 357 | <div className="grid gap-6 lg:grid-cols-2"> |
| 358 | {featuredServices.map((service) => ( |
| 359 | <Link |
| 360 | key={service.name} |
| 361 | href={service.href} |
| 362 | className={`group rounded-2xl border p-8 transition-colors ${ |
| 363 | service.accent === "orange" |
| 364 | ? "border-orange-200 bg-orange-50/70 hover:border-orange-300 hover:bg-orange-50 dark:border-orange-500/20 dark:bg-orange-500/10 dark:hover:border-orange-500/35 dark:hover:bg-orange-500/14" |
| 365 | : "border-indigo-200 bg-indigo-50/70 hover:border-indigo-300 hover:bg-indigo-50 dark:border-indigo-500/20 dark:bg-indigo-500/10 dark:hover:border-indigo-500/35 dark:hover:bg-indigo-500/14" |
| 366 | }`} |
| 367 | > |
| 368 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-500 dark:text-slate-500"> |
| 369 | {service.eyebrow} |
| 370 | </p> |
| 371 | <h3 className="mt-4 text-2xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 372 | {service.title} |
| 373 | </h3> |
| 374 | <p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 375 | {service.description} |
| 376 | </p> |
| 377 | <ul className="mt-6 space-y-3 text-sm leading-6 text-slate-600 dark:text-slate-400"> |
| 378 | {service.bullets.map((bullet) => ( |
| 379 | <li key={bullet} className="flex gap-3"> |
| 380 | <span |
| 381 | className={`mt-2 h-1.5 w-1.5 shrink-0 rounded-full ${ |
| 382 | service.accent === "orange" |
| 383 | ? "bg-orange-500" |
| 384 | : "bg-indigo-500" |
| 385 | }`} |
| 386 | /> |
| 387 | <span>{bullet}</span> |
| 388 | </li> |
| 389 | ))} |
| 390 | </ul> |
| 391 | <p |
| 392 | className={`mt-6 text-sm font-semibold ${ |
| 393 | service.accent === "orange" |
| 394 | ? "text-orange-600 dark:text-orange-400" |
| 395 | : "text-indigo-600 dark:text-indigo-400" |
| 396 | }`} |
| 397 | > |
| 398 | {service.cta} → |
| 399 | </p> |
| 400 | </Link> |
| 401 | ))} |
| 402 | </div> |
| 403 | </div> |
| 404 | </section> |
| 405 | |
| 406 | <section className="px-6 pb-12 lg:px-8"> |
| 407 | <div className="mx-auto grid max-w-5xl gap-4 sm:grid-cols-2 lg:grid-cols-4"> |
| 408 | {proofPoints.map((point) => ( |
| 409 | <div |
| 410 | key={point.title} |
| 411 | className="rounded-xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-5" |
| 412 | > |
| 413 | <p className="text-sm font-semibold text-slate-900 dark:text-white"> |
| 414 | {point.title} |
| 415 | </p> |
| 416 | <p className="mt-2 text-sm leading-relaxed text-slate-500 dark:text-slate-400"> |
| 417 | {point.description} |
| 418 | </p> |
| 419 | </div> |
| 420 | ))} |
| 421 | </div> |
| 422 | </section> |
| 423 | |
| 424 | <section className="px-6 pb-28 lg:px-8"> |
| 425 | <div className="mx-auto max-w-3xl"> |
| 426 | <p className="mb-8 text-center text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 427 | One CLI. Multiple runtimes. |
| 428 | </p> |
| 429 | <TabbedRunner /> |
| 430 | </div> |
| 431 | </section> |
| 432 | |
| 433 | <section className="border-t border-slate-200 dark:border-white/[0.06] px-6 py-24 lg:px-8"> |
| 434 | <div className="mx-auto max-w-5xl"> |
| 435 | <div className="mb-16 max-w-3xl"> |
| 436 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 437 | Why smbCloud |
| 438 | </p> |
| 439 | <h2 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-4xl"> |
| 440 | Deploys should be boring. |
| 441 | </h2> |
| 442 | <p className="mt-5 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 443 | Run `smb`. Watch the logs. Move on. |
| 444 | </p> |
| 445 | </div> |
| 446 | |
| 447 | <div className="grid grid-cols-1 gap-6 lg:grid-cols-3"> |
| 448 | {reasonsToChoose.map((reason) => ( |
| 449 | <div |
| 450 | key={reason.title} |
| 451 | className="rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-6" |
| 452 | > |
| 453 | <h3 className="text-lg font-semibold text-slate-900 dark:text-white"> |
| 454 | {reason.title} |
| 455 | </h3> |
| 456 | <p className="mt-3 text-sm leading-7 text-slate-500 dark:text-slate-400"> |
| 457 | {reason.description} |
| 458 | </p> |
| 459 | </div> |
| 460 | ))} |
| 461 | </div> |
| 462 | </div> |
| 463 | </section> |
| 464 | |
| 465 | <section className="px-6 pb-24 lg:px-8"> |
| 466 | <div className="mx-auto grid max-w-5xl gap-8 lg:grid-cols-[1.1fr_0.9fr]"> |
| 467 | <div className="rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-8"> |
| 468 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 469 | Who it fits best |
| 470 | </p> |
| 471 | <h2 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 472 | Good fit |
| 473 | </h2> |
| 474 | <ul className="mt-6 space-y-4 text-sm leading-7 text-slate-600 dark:text-slate-400"> |
| 475 | {bestFit.map((item) => ( |
| 476 | <li key={item} className="flex gap-3"> |
| 477 | <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-500" /> |
| 478 | <span>{item}</span> |
| 479 | </li> |
| 480 | ))} |
| 481 | </ul> |
| 482 | </div> |
| 483 | |
| 484 | <div className="rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-slate-50 dark:bg-white/[0.02] p-8"> |
| 485 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 486 | Stack focus |
| 487 | </p> |
| 488 | <h2 className="mt-4 text-2xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 489 | Supported stacks |
| 490 | </h2> |
| 491 | <div className="mt-6 space-y-4 text-sm text-slate-600 dark:text-slate-400"> |
| 492 | <div className="rounded-xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.03] p-4"> |
| 493 | <p className="font-semibold text-slate-900 dark:text-white"> |
| 494 | Node.js |
| 495 | </p> |
| 496 | <p className="mt-1 leading-7"> |
| 497 | Web apps, APIs, dashboards, backend services. |
| 498 | </p> |
| 499 | </div> |
| 500 | <div className="rounded-xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.03] p-4"> |
| 501 | <p className="font-semibold text-slate-900 dark:text-white"> |
| 502 | Ruby on Rails |
| 503 | </p> |
| 504 | <p className="mt-1 leading-7"> |
| 505 | Still my favorite stack for shipping fast. |
| 506 | </p> |
| 507 | </div> |
| 508 | <div className="rounded-xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.03] p-4"> |
| 509 | <p className="font-semibold text-slate-900 dark:text-white"> |
| 510 | Swift / Vapor |
| 511 | </p> |
| 512 | <p className="mt-1 leading-7"> |
| 513 | Works. Doesn't treat Vapor as an afterthought. |
| 514 | </p> |
| 515 | </div> |
| 516 | </div> |
| 517 | </div> |
| 518 | </div> |
| 519 | </section> |
| 520 | |
| 521 | <section className="border-t border-slate-200 dark:border-white/[0.06] px-6 py-24 lg:px-8"> |
| 522 | <div className="mx-auto max-w-5xl"> |
| 523 | <div className="mb-16 max-w-3xl"> |
| 524 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 525 | Compare services |
| 526 | </p> |
| 527 | <h2 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-4xl"> |
| 528 | Pick the service you're comparing. |
| 529 | </h2> |
| 530 | </div> |
| 531 | |
| 532 | <div className="space-y-16"> |
| 533 | <div> |
| 534 | <div className="mb-10 max-w-3xl"> |
| 535 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 536 | smbCloud Auth |
| 537 | </p> |
| 538 | <h3 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 539 | Auth0, Clerk, or Supabase Auth? |
| 540 | </h3> |
| 541 | <p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 542 | Sign-in, signup, sessions. Hosted, out of the way. |
| 543 | </p> |
| 544 | </div> |
| 545 | |
| 546 | <div className="grid gap-6 lg:grid-cols-3"> |
| 547 | {authComparisonPages.map((page) => ( |
| 548 | <Link |
| 549 | key={page.href} |
| 550 | href={page.href} |
| 551 | className="group rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-8 transition-colors hover:border-indigo-300 dark:hover:border-indigo-700/50 hover:bg-slate-50 dark:hover:bg-white/[0.04]" |
| 552 | > |
| 553 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 554 | {page.eyebrow} |
| 555 | </p> |
| 556 | <h4 className="mt-4 text-2xl font-semibold tracking-tight text-slate-900 transition-colors group-hover:text-indigo-600 dark:text-white dark:group-hover:text-indigo-400"> |
| 557 | {page.title} |
| 558 | </h4> |
| 559 | <p className="mt-4 text-sm leading-7 text-slate-600 dark:text-slate-400"> |
| 560 | {page.description} |
| 561 | </p> |
| 562 | <ul className="mt-5 space-y-3 text-sm leading-6 text-slate-500 dark:text-slate-400"> |
| 563 | {page.bullets.map((bullet) => ( |
| 564 | <li key={bullet} className="flex gap-3"> |
| 565 | <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-500" /> |
| 566 | <span>{bullet}</span> |
| 567 | </li> |
| 568 | ))} |
| 569 | </ul> |
| 570 | <p className="mt-6 text-sm font-semibold text-indigo-600 dark:text-indigo-400"> |
| 571 | Read comparison → |
| 572 | </p> |
| 573 | </Link> |
| 574 | ))} |
| 575 | </div> |
| 576 | </div> |
| 577 | |
| 578 | <div className="border-t border-slate-200 pt-16 dark:border-white/[0.06]"> |
| 579 | <div className="mb-10 max-w-3xl"> |
| 580 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 581 | smbCloud Mail |
| 582 | </p> |
| 583 | <h3 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 584 | Resend, useSend, or SendGrid? |
| 585 | </h3> |
| 586 | <p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 587 | Domain routes, forwarding, stored inbound mail. |
| 588 | </p> |
| 589 | </div> |
| 590 | |
| 591 | <div className="grid gap-6 lg:grid-cols-3"> |
| 592 | {mailComparisonPages.map((page) => ( |
| 593 | <Link |
| 594 | key={page.href} |
| 595 | href={page.href} |
| 596 | className="group rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-8 transition-colors hover:border-indigo-300 dark:hover:border-indigo-700/50 hover:bg-slate-50 dark:hover:bg-white/[0.04]" |
| 597 | > |
| 598 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 599 | {page.eyebrow} |
| 600 | </p> |
| 601 | <h4 className="mt-4 text-2xl font-semibold tracking-tight text-slate-900 transition-colors group-hover:text-indigo-600 dark:text-white dark:group-hover:text-indigo-400"> |
| 602 | {page.title} |
| 603 | </h4> |
| 604 | <p className="mt-4 text-sm leading-7 text-slate-600 dark:text-slate-400"> |
| 605 | {page.description} |
| 606 | </p> |
| 607 | <ul className="mt-5 space-y-3 text-sm leading-6 text-slate-500 dark:text-slate-400"> |
| 608 | {page.bullets.map((bullet) => ( |
| 609 | <li key={bullet} className="flex gap-3"> |
| 610 | <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-500" /> |
| 611 | <span>{bullet}</span> |
| 612 | </li> |
| 613 | ))} |
| 614 | </ul> |
| 615 | <p className="mt-6 text-sm font-semibold text-indigo-600 dark:text-indigo-400"> |
| 616 | Read comparison → |
| 617 | </p> |
| 618 | </Link> |
| 619 | ))} |
| 620 | </div> |
| 621 | </div> |
| 622 | |
| 623 | <div className="border-t border-slate-200 pt-16 dark:border-white/[0.06]"> |
| 624 | <div className="mb-10 max-w-3xl"> |
| 625 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 626 | smbCloud Deploy |
| 627 | </p> |
| 628 | <h3 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 629 | Heroku or Railway? |
| 630 | </h3> |
| 631 | <p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 632 | Direct comparisons, honest about where smbCloud fits and where |
| 633 | it doesn't. |
| 634 | </p> |
| 635 | </div> |
| 636 | |
| 637 | <div className="grid gap-6 lg:grid-cols-2"> |
| 638 | {deployComparisonPages.map((page) => ( |
| 639 | <Link |
| 640 | key={page.href} |
| 641 | href={page.href} |
| 642 | className="group rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-8 transition-colors hover:border-indigo-300 dark:hover:border-indigo-700/50 hover:bg-slate-50 dark:hover:bg-white/[0.04]" |
| 643 | > |
| 644 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 645 | {page.eyebrow} |
| 646 | </p> |
| 647 | <h4 className="mt-4 text-2xl font-semibold tracking-tight text-slate-900 transition-colors group-hover:text-indigo-600 dark:text-white dark:group-hover:text-indigo-400"> |
| 648 | {page.title} |
| 649 | </h4> |
| 650 | <p className="mt-4 text-sm leading-7 text-slate-600 dark:text-slate-400"> |
| 651 | {page.description} |
| 652 | </p> |
| 653 | <ul className="mt-5 space-y-3 text-sm leading-6 text-slate-500 dark:text-slate-400"> |
| 654 | {page.bullets.map((bullet) => ( |
| 655 | <li key={bullet} className="flex gap-3"> |
| 656 | <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-500" /> |
| 657 | <span>{bullet}</span> |
| 658 | </li> |
| 659 | ))} |
| 660 | </ul> |
| 661 | <p className="mt-6 text-sm font-semibold text-indigo-600 dark:text-indigo-400"> |
| 662 | Read comparison → |
| 663 | </p> |
| 664 | </Link> |
| 665 | ))} |
| 666 | </div> |
| 667 | </div> |
| 668 | |
| 669 | <div className="border-t border-slate-200 pt-16 dark:border-white/[0.06]"> |
| 670 | <div className="mb-10 max-w-3xl"> |
| 671 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 672 | smbCloud GresIQ |
| 673 | </p> |
| 674 | <h3 className="mt-4 text-3xl font-bold tracking-tight text-slate-900 dark:text-white"> |
| 675 | Supabase, PlanetScale, or Neon? |
| 676 | </h3> |
| 677 | <p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-400"> |
| 678 | A data layer that lives with your stack, not next to it. |
| 679 | </p> |
| 680 | </div> |
| 681 | |
| 682 | <div className="grid gap-6 lg:grid-cols-3"> |
| 683 | {gresiqComparisonPages.map((page) => ( |
| 684 | <Link |
| 685 | key={page.href} |
| 686 | href={page.href} |
| 687 | className="group rounded-2xl border border-slate-200 dark:border-white/[0.06] bg-white dark:bg-white/[0.02] p-8 transition-colors hover:border-indigo-300 dark:hover:border-indigo-700/50 hover:bg-slate-50 dark:hover:bg-white/[0.04]" |
| 688 | > |
| 689 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 690 | {page.eyebrow} |
| 691 | </p> |
| 692 | <h4 className="mt-4 text-2xl font-semibold tracking-tight text-slate-900 transition-colors group-hover:text-indigo-600 dark:text-white dark:group-hover:text-indigo-400"> |
| 693 | {page.title} |
| 694 | </h4> |
| 695 | <p className="mt-4 text-sm leading-7 text-slate-600 dark:text-slate-400"> |
| 696 | {page.description} |
| 697 | </p> |
| 698 | <ul className="mt-5 space-y-3 text-sm leading-6 text-slate-500 dark:text-slate-400"> |
| 699 | {page.bullets.map((bullet) => ( |
| 700 | <li key={bullet} className="flex gap-3"> |
| 701 | <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-500" /> |
| 702 | <span>{bullet}</span> |
| 703 | </li> |
| 704 | ))} |
| 705 | </ul> |
| 706 | <p className="mt-6 text-sm font-semibold text-indigo-600 dark:text-indigo-400"> |
| 707 | Read comparison → |
| 708 | </p> |
| 709 | </Link> |
| 710 | ))} |
| 711 | </div> |
| 712 | </div> |
| 713 | </div> |
| 714 | </div> |
| 715 | </section> |
| 716 | |
| 717 | <section className="px-6 py-16 lg:px-8"> |
| 718 | <div className="mx-auto max-w-2xl"> |
| 719 | <div className="relative overflow-hidden rounded-2xl bg-indigo-600 px-8 py-14 text-center shadow-2xl shadow-indigo-500/20"> |
| 720 | <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(255,255,255,0.1),transparent)]" /> |
| 721 | <h2 className="relative text-3xl font-bold tracking-tight text-white"> |
| 722 | Try it on one app. |
| 723 | </h2> |
| 724 | <p className="relative mt-4 text-indigo-200"> |
| 725 | Create an account and install the CLI. |
| 726 | </p> |
| 727 | <div className="relative mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row"> |
| 728 | <Link |
| 729 | href="https://console.smbcloud.xyz" |
| 730 | target="_blank" |
| 731 | rel="noopener noreferrer" |
| 732 | className="inline-flex rounded-lg bg-white px-8 py-3.5 text-sm font-semibold text-indigo-700 shadow-sm transition-colors hover:bg-indigo-50" |
| 733 | > |
| 734 | Create free account → |
| 735 | </Link> |
| 736 | <Link |
| 737 | href="/services" |
| 738 | className="inline-flex rounded-lg border border-white/20 px-8 py-3.5 text-sm font-semibold text-white transition-colors hover:bg-white/10" |
| 739 | > |
| 740 | Explore services |
| 741 | </Link> |
| 742 | </div> |
| 743 | </div> |
| 744 | </div> |
| 745 | </section> |
| 746 | |
| 747 | {publishedPosts.length > 0 && ( |
| 748 | <section className="border-t border-slate-200 dark:border-white/[0.06] px-6 py-24 lg:px-8"> |
| 749 | <div className="mx-auto max-w-5xl"> |
| 750 | <div className="mb-10 flex items-end justify-between gap-4"> |
| 751 | <p className="text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-600"> |
| 752 | From the blog |
| 753 | </p> |
| 754 | <Link |
| 755 | href="/posts" |
| 756 | className="text-sm font-semibold text-indigo-600 transition-colors hover:text-indigo-500 dark:text-indigo-400" |
| 757 | > |
| 758 | View all posts |
| 759 | </Link> |
| 760 | </div> |
| 761 | <div className="space-y-6"> |
| 762 | {publishedPosts.slice(0, 3).map((post) => ( |
| 763 | <article |
| 764 | key={post._id} |
| 765 | className="group border-b border-slate-200 dark:border-white/[0.06] pb-6 last:border-0" |
| 766 | > |
| 767 | <Link href={post.slug} className="block"> |
| 768 | <h3 className="font-semibold text-slate-900 dark:text-white transition-colors group-hover:text-indigo-600 dark:group-hover:text-indigo-400"> |
| 769 | {post.title} |
| 770 | </h3> |
| 771 | {post.description && ( |
| 772 | <p className="mt-1 text-sm text-slate-500 dark:text-slate-400"> |
| 773 | {post.description} |
| 774 | </p> |
| 775 | )} |
| 776 | </Link> |
| 777 | </article> |
| 778 | ))} |
| 779 | </div> |
| 780 | </div> |
| 781 | </section> |
| 782 | )} |
| 783 | |
| 784 | <section className="px-6 pb-16 lg:px-8"> |
| 785 | <div className="mx-auto max-w-2xl"> |
| 786 | <div className="relative overflow-hidden rounded-2xl border border-slate-800 bg-slate-900 px-8 py-12 dark:border-white/[0.08] dark:bg-white/[0.04]"> |
| 787 | <div className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" /> |
| 788 | |
| 789 | <p className="mb-5 text-xs font-bold uppercase tracking-[0.2em] text-slate-500"> |
| 790 | Also from smbCloud |
| 791 | </p> |
| 792 | |
| 793 | <div className="mb-4 flex items-center gap-3"> |
| 794 | <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-white text-slate-900"> |
| 795 | <span className="text-xs font-black tracking-tighter leading-none"> |
| 796 | si |
| 797 | </span> |
| 798 | </div> |
| 799 | <h2 className="text-2xl font-bold tracking-tight text-white"> |
| 800 | siGit Code & Deploy |
| 801 | </h2> |
| 802 | </div> |
| 803 | |
| 804 | <p className="mb-2 max-w-md text-sm leading-relaxed text-slate-300 dark:text-slate-400"> |
| 805 | <span className="font-semibold text-white">smbcloud-cli</span> as |
| 806 | a native app. Review changes, edit, and deploy from your phone. |
| 807 | </p> |
| 808 | <p className="mb-8 text-xs italic text-slate-500"> |
| 809 | Available on iPhone, Android, and Windows. |
| 810 | </p> |
| 811 | |
| 812 | <div className="flex flex-wrap gap-3"> |
| 813 | <a |
| 814 | href="https://apps.apple.com/se/app/sigit-git-client-code-editor/id6753018849" |
| 815 | target="_blank" |
| 816 | rel="noopener noreferrer" |
| 817 | className="inline-flex items-center gap-2 rounded-lg border border-white/20 bg-white/10 px-4 py-2.5 text-xs font-semibold text-white transition-colors hover:bg-white/20" |
| 818 | > |
| 819 | <FaApple className="h-4 w-4" /> |
| 820 | App Store |
| 821 | </a> |
| 822 | <a |
| 823 | href="https://play.google.com/store/apps/details?id=xyz.smbcloud.SiGit" |
| 824 | target="_blank" |
| 825 | rel="noopener noreferrer" |
| 826 | className="inline-flex items-center gap-2 rounded-lg border border-white/20 bg-white/10 px-4 py-2.5 text-xs font-semibold text-white transition-colors hover:bg-white/20" |
| 827 | > |
| 828 | <FaGooglePlay className="h-4 w-4" /> |
| 829 | Google Play |
| 830 | </a> |
| 831 | <a |
| 832 | href="https://apps.microsoft.com/detail/xp9k321rf5mzsz?ocid=webpdpshare" |
| 833 | target="_blank" |
| 834 | rel="noopener noreferrer" |
| 835 | className="inline-flex items-center gap-2 rounded-lg border border-white/20 bg-white/10 px-4 py-2.5 text-xs font-semibold text-white transition-colors hover:bg-white/20" |
| 836 | > |
| 837 | <FaWindows className="h-4 w-4" /> |
| 838 | Microsoft Store |
| 839 | </a> |
| 840 | </div> |
| 841 | </div> |
| 842 | </div> |
| 843 | </section> |
| 844 | </div> |
| 845 | ); |
| 846 | } |