| 1 | import { |
| 2 | ArrowRight, |
| 3 | Check, |
| 4 | Code, |
| 5 | Eye, |
| 6 | Lock, |
| 7 | MessageSquare, |
| 8 | Palette, |
| 9 | Pen, |
| 10 | PenTool, |
| 11 | Send, |
| 12 | Users, |
| 13 | Video, |
| 14 | } from 'lucide-react' |
| 15 | import Link from 'next/link |
| 16 | |
| 17 | import { SaturnLogo } |
| 18 | import { buttonVariants } |
| 19 | |
| 20 | import { |
| 21 | capabilities, |
| 22 | clientFeatures, |
| 23 | freelancerTypes, |
| 24 | freePlanFeatures, |
| 25 | proPlanFeatures, |
| 26 | roles, |
| 27 | workflowSteps, |
| 28 | } from './_landing/data' |
| 29 | import { DotPattern } |
| 30 | import { MockAppUI } |
| 31 | import { MockInvoiceUI } |
| 32 | import { MockRequirementUI } |
| 33 | import { MockTimesheetUI } |
| 34 | |
| 35 | const freelancerIcons = { |
| 36 | const clientIcons = { |
| 37 | |
| 38 | export default function LandingPage |
| 39 | return ( |
| 40 | <div className='min-h-svh w-full bg-background text-foreground |
| 41 | <nav className='sticky top-0 z-50 border-border/50 border-b bg-background/80 backdrop-blur-xl |
| 42 | <div className='mx-auto flex h-14 max-w-7xl items-center justify-between px-6 |
| 43 | <Link className=' |
| 44 | <SaturnLogo className=' |
| 45 | <span className='font-semibold text-lg tracking-tight |
| 46 | </Link> |
| 47 | <div className='flex items-center gap-2 |
| 48 | <Link |
| 49 | className={buttonVariants({ |
| 50 | href='#pricing' |
| 51 | > |
| 52 | Pricing |
| 53 | </Link> |
| 54 | <Link |
| 55 | className={buttonVariants({ |
| 56 | href='/auth/sign-in' |
| 57 | > |
| 58 | Sign in |
| 59 | </Link> |
| 60 | <Link |
| 61 | className={buttonVariants({ |
| 62 | href='/auth/sign-up' |
| 63 | > |
| 64 | Get started |
| 65 | <ArrowRight className=' |
| 66 | </Link> |
| 67 | </div> |
| 68 | </div> |
| 69 | </nav> |
| 70 | |
| 71 | <section className='relative overflow-hidden |
| 72 | <DotPattern className=' |
| 73 | <div className='relative mx-auto grid max-w-7xl gap-16 px-6 pt-20 pb-20 lg:grid-cols-2 lg:gap-12 lg:pt-28 |
| 74 | <div className='flex flex-col justify-center |
| 75 | <h1 className='font-bold text-4xl tracking-tight lg:text-5xl |
| 76 | The operating system for your freelance business |
| 77 | </h1> |
| 78 | <p className='mt-5 max-w-lg text-lg text-muted-foreground leading-relaxed |
| 79 | Saturn brings projects, timesheets, invoices, and client |
| 80 | management into one place. No more spreadsheets. No more chasing |
| 81 | emails. Just open Saturn and get to work. |
| 82 | </p> |
| 83 | <div className='mt-8 flex items-center gap-3 |
| 84 | <Link |
| 85 | className={buttonVariants({ |
| 86 | href='/auth/sign-up' |
| 87 | > |
| 88 | Start for free |
| 89 | <ArrowRight className=' |
| 90 | </Link> |
| 91 | <Link |
| 92 | className={buttonVariants({ |
| 93 | href='#how-it-works' |
| 94 | > |
| 95 | See how it works |
| 96 | </Link> |
| 97 | </div> |
| 98 | </div> |
| 99 | <div className='relative lg:pt-4 |
| 100 | <MockAppUI /> |
| 101 | </div> |
| 102 | </div> |
| 103 | </section> |
| 104 | |
| 105 | <section className='border-border border-y bg-secondary/40 |
| 106 | <div className='mx-auto max-w-7xl px-6 py-24 |
| 107 | <div className='mb-14 |
| 108 | <h2 className='font-bold text-3xl tracking-tight |
| 109 | What you can do with Saturn |
| 110 | </h2> |
| 111 | <p className='mt-2 max-w-lg text-muted-foreground |
| 112 | Six modules that cover the full lifecycle of a freelance project. |
| 113 | </p> |
| 114 | </div> |
| 115 | <div className='grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-2 lg:grid-cols-3 |
| 116 | {capabilities.map(( |
| 117 | <div className='bg-card p-6 |
| 118 | <cap.icon className=' |
| 119 | <h3 className='mb-1.5 font-semibold |
| 120 | <p className='text-muted-foreground text-sm leading-relaxed |
| 121 | {cap.desc} |
| 122 | </p> |
| 123 | </div> |
| 124 | ))} |
| 125 | </div> |
| 126 | </div> |
| 127 | </section> |
| 128 | |
| 129 | <section className='relative |
| 130 | <DotPattern className=' |
| 131 | <div className='relative mx-auto max-w-7xl px-6 py-24 |
| 132 | <div className='mb-14 |
| 133 | <h2 className='font-bold text-3xl tracking-tight |
| 134 | From tracked hours to paid invoices |
| 135 | </h2> |
| 136 | <p className='mt-2 max-w-lg text-muted-foreground |
| 137 | Log time against requirements. Generate invoices from that data. |
| 138 | Send them to clients. Done. |
| 139 | </p> |
| 140 | </div> |
| 141 | <div className='grid gap-10 lg:grid-cols-2 lg:gap-16 |
| 142 | <MockTimesheetUI /> |
| 143 | <MockInvoiceUI /> |
| 144 | </div> |
| 145 | <div className='mt-12 grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-3 |
| 146 | {workflowSteps.map(( |
| 147 | <div className='bg-card p-6 |
| 148 | <span className='mb-3 inline-block font-mono text-primary text-xs |
| 149 | {s.step} |
| 150 | </span> |
| 151 | <h3 className='mb-1.5 font-semibold |
| 152 | <p className='text-muted-foreground text-sm leading-relaxed |
| 153 | {s.desc} |
| 154 | </p> |
| 155 | </div> |
| 156 | ))} |
| 157 | </div> |
| 158 | </div> |
| 159 | </section> |
| 160 | |
| 161 | <section className='border-border border-y bg-secondary/40 |
| 162 | <div className='mx-auto max-w-7xl px-6 py-24 |
| 163 | <div className='grid gap-16 lg:grid-cols-2 |
| 164 | <div> |
| 165 | <h2 className='font-bold text-3xl tracking-tight |
| 166 | Write requirements. Get them signed. |
| 167 | </h2> |
| 168 | <p className='mt-3 max-w-md text-muted-foreground |
| 169 | Saturn has a full rich-text editor for writing project |
| 170 | requirements. When they're ready, send them to your client |
| 171 | for review. Clients can request changes, leave threaded |
| 172 | comments, or sign off with a digital signature — all without |
| 173 | leaving Saturn. |
| 174 | </p> |
| 175 | <div className='mt-8 space-y-4 |
| 176 | {[ |
| 177 | { |
| 178 | icon: Pen, |
| 179 | text: 'Write requirements with a rich-text editor — images, code blocks, and all', |
| 180 | }, |
| 181 | { |
| 182 | icon: Send, |
| 183 | text: "Send to clients for review when you're ready", |
| 184 | }, |
| 185 | { |
| 186 | icon: MessageSquare, |
| 187 | text: 'Clients leave threaded comments or request changes inline', |
| 188 | }, |
| 189 | { |
| 190 | icon: PenTool, |
| 191 | text: 'Collect digital signatures once requirements are approved', |
| 192 | }, |
| 193 | ].map((item |
| 194 | <div className='flex gap-3 |
| 195 | <item.icon className=' |
| 196 | <span className='text-muted-foreground text-sm |
| 197 | {item.text} |
| 198 | </span> |
| 199 | </div> |
| 200 | ))} |
| 201 | </div> |
| 202 | </div> |
| 203 | <MockRequirementUI /> |
| 204 | </div> |
| 205 | </div> |
| 206 | </section> |
| 207 | |
| 208 | <section> |
| 209 | <div className='mx-auto max-w-7xl px-6 py-24 |
| 210 | <h2 className='font-bold text-3xl tracking-tight |
| 211 | Roles that match how teams actually work |
| 212 | </h2> |
| 213 | <p className='mt-3 max-w-lg text-muted-foreground |
| 214 | Four roles with fine-grained permissions. Your team sees exactly |
| 215 | what they need — nothing more. Clients register on the same platform |
| 216 | with scoped access to their assigned projects. |
| 217 | </p> |
| 218 | <div className='mt-12 grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-2 lg:grid-cols-4 |
| 219 | {roles.map(( |
| 220 | <div className='bg-card p-6 |
| 221 | <div className='mb-1 font-semibold |
| 222 | <p className='text-muted-foreground text-sm |
| 223 | <div className='mt-4 space-y-1.5 |
| 224 | {r.permissions.map |
| 225 | <div |
| 226 | className='flex items-center gap-2 text-muted-foreground text-xs' |
| 227 | key={p} |
| 228 | > |
| 229 | <Check className=' |
| 230 | {p} |
| 231 | </div> |
| 232 | ))} |
| 233 | </div> |
| 234 | </div> |
| 235 | ))} |
| 236 | </div> |
| 237 | </div> |
| 238 | </section> |
| 239 | |
| 240 | <section className='relative border-border border-y bg-secondary/40 |
| 241 | <DotPattern className=' |
| 242 | <div className='relative mx-auto max-w-7xl px-6 py-24 |
| 243 | <h2 className='font-bold text-3xl tracking-tight |
| 244 | Built for every kind of freelancer |
| 245 | </h2> |
| 246 | <p className='mt-3 max-w-lg text-muted-foreground |
| 247 | Whether you're a solo developer or a design agency with 20 |
| 248 | people, Saturn adapts to how you work. |
| 249 | </p> |
| 250 | <div className='mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-4 |
| 251 | {freelancerTypes.map(( |
| 252 | const Icon = |
| 253 | return ( |
| 254 | <div |
| 255 | className='rounded-xl border border-border bg-card p-5' |
| 256 | key={cat.title |
| 257 | > |
| 258 | <Icon className=' |
| 259 | <h3 className='mb-3 font-semibold |
| 260 | <ul className='space-y-2 |
| 261 | {cat.points.map |
| 262 | <li |
| 263 | className='flex gap-2 text-muted-foreground text-sm' |
| 264 | key={point} |
| 265 | > |
| 266 | <span className='mt-1.5 size-1 shrink-0 rounded-full bg-primary |
| 267 | {point} |
| 268 | </li> |
| 269 | ))} |
| 270 | </ul> |
| 271 | </div> |
| 272 | ) |
| 273 | })} |
| 274 | </div> |
| 275 | </div> |
| 276 | </section> |
| 277 | |
| 278 | <section> |
| 279 | <div className='mx-auto max-w-7xl px-6 py-24 |
| 280 | <h2 className='font-bold text-3xl tracking-tight |
| 281 | Your clients use the same platform |
| 282 | </h2> |
| 283 | <p className='mt-3 max-w-lg text-muted-foreground |
| 284 | No separate portal. Clients register on Saturn and get invited to |
| 285 | your projects. Their role scopes what they can see — milestone |
| 286 | progress, requirements to sign, invoices to review — while your |
| 287 | internal timesheets and team rates stay private. |
| 288 | </p> |
| 289 | <div className='mt-12 grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-2 lg:grid-cols-4 |
| 290 | {clientFeatures.map(( |
| 291 | const Icon = |
| 292 | return ( |
| 293 | <div className='bg-card p-5 |
| 294 | <Icon className=' |
| 295 | <div className='mb-1 font-semibold text-sm |
| 296 | <p className='text-muted-foreground text-xs leading-relaxed |
| 297 | {item.desc} |
| 298 | </p> |
| 299 | </div> |
| 300 | ) |
| 301 | })} |
| 302 | </div> |
| 303 | </div> |
| 304 | </section> |
| 305 | |
| 306 | <section |
| 307 | className='relative border-border border-y bg-secondary/40' |
| 308 | id='pricing' |
| 309 | > |
| 310 | <DotPattern className=' |
| 311 | <div className='relative mx-auto max-w-4xl px-6 py-24 |
| 312 | <div className='mb-14 text-center |
| 313 | <h2 className='font-bold text-3xl tracking-tight |
| 314 | Simple pricing. No per-seat nonsense. |
| 315 | </h2> |
| 316 | <p className='mt-3 text-muted-foreground |
| 317 | Every feature works on Free. Pro removes limits and adds API |
| 318 | access for teams that want to automate. |
| 319 | </p> |
| 320 | </div> |
| 321 | <div className='grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-2 |
| 322 | <div className='flex flex-col bg-card p-8 |
| 323 | <div className='mb-1 font-semibold text-lg |
| 324 | <div className='mb-4 flex items-baseline gap-1 |
| 325 | <span className='font-bold text-3xl tracking-tight |
| 326 | <span className='text-muted-foreground text-sm |
| 327 | </div> |
| 328 | <p className='mb-6 text-muted-foreground text-sm |
| 329 | Everything you need to manage a small freelance practice. |
| 330 | </p> |
| 331 | <div className='mb-8 space-y-3 |
| 332 | {freePlanFeatures.map(( |
| 333 | <div className='flex items-center gap-2.5 text-sm |
| 334 | <Check className=' |
| 335 | {f} |
| 336 | </div> |
| 337 | ))} |
| 338 | </div> |
| 339 | <div className='mt-auto |
| 340 | <Link |
| 341 | className={buttonVariants({ |
| 342 | variant: 'outline', |
| 343 | size: 'lg', |
| 344 | className: 'w-full', |
| 345 | })} |
| 346 | href='/auth/sign-up' |
| 347 | > |
| 348 | Get started |
| 349 | </Link> |
| 350 | </div> |
| 351 | </div> |
| 352 | <div className='flex flex-col bg-card p-8 |
| 353 | <div className='mb-1 flex items-center gap-2 |
| 354 | <span className='font-semibold text-lg |
| 355 | <span className='rounded-md bg-primary/10 px-2 py-0.5 font-medium text-primary text-xs |
| 356 | Recommended |
| 357 | </span> |
| 358 | </div> |
| 359 | <div className='mb-4 flex items-baseline gap-1 |
| 360 | <span className='font-bold text-3xl tracking-tight |
| 361 | <span className='text-muted-foreground text-sm |
| 362 | </div> |
| 363 | <p className='mb-6 text-muted-foreground text-sm |
| 364 | For freelancers and agencies that need room to grow. |
| 365 | </p> |
| 366 | <div className='mb-8 space-y-3 |
| 367 | {proPlanFeatures.map(( |
| 368 | <div className='flex items-center gap-2.5 text-sm |
| 369 | <Check className=' |
| 370 | {f} |
| 371 | </div> |
| 372 | ))} |
| 373 | </div> |
| 374 | <div className='mt-auto |
| 375 | <Link |
| 376 | className={buttonVariants({ |
| 377 | size: 'lg', |
| 378 | className: 'w-full', |
| 379 | })} |
| 380 | href='/auth/sign-up' |
| 381 | > |
| 382 | Start with Pro |
| 383 | </Link> |
| 384 | </div> |
| 385 | </div> |
| 386 | </div> |
| 387 | <p className='mt-6 text-center text-muted-foreground text-sm |
| 388 | No credit card required. No feature gates on core functionality. |
| 389 | </p> |
| 390 | </div> |
| 391 | </section> |
| 392 | |
| 393 | <section className='mx-auto max-w-2xl px-6 py-24 text-center |
| 394 | <h2 className='font-bold text-3xl tracking-tight |
| 395 | Stop juggling tools. |
| 396 | <br /> |
| 397 | Start running your business. |
| 398 | </h2> |
| 399 | <p className='mt-4 text-lg text-muted-foreground |
| 400 | Saturn is free to get started. Set up your first project in under two |
| 401 | minutes. |
| 402 | </p> |
| 403 | <div className='mt-8 |
| 404 | <Link className={ |
| 405 | Get started for free |
| 406 | <ArrowRight className=' |
| 407 | </Link> |
| 408 | </div> |
| 409 | </section> |
| 410 | |
| 411 | <footer className='border-border border-t bg-secondary/40 |
| 412 | <div className='mx-auto flex max-w-7xl items-center justify-between px-6 py-6 |
| 413 | <div className='flex items-center gap-2 |
| 414 | <SaturnLogo className=' |
| 415 | <span className='text-muted-foreground text-sm |
| 416 | </div> |
| 417 | <p className='text-muted-foreground text-xs |
| 418 | © {new |
| 419 | </p> |
| 420 | </div> |
| 421 | </footer> |
| 422 | </div> |
| 423 | ) |
| 424 | } |