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