Files
hanzo.ai/app/(marketing)/careers/page.tsx
Cursor Agentandz c3af929c56 site: one API, one account, better cheaper faster
The bar is Models, Dev, Platform, Pricing, Docs, Enterprise, Log in, and Get API key. The homepage is seven sections. Launch pages stay in the tree and drop out of the index through lib/launch.ts. /platform forwards to /cloud. Model and repository floors come from the snapshots the build already keeps.

Co-authored-by: z <[email protected]>
2026-10-26 21:53:40 +00:00

627 lines
26 KiB
TypeScript

"use client"
/**
* /careers — the openings, the terms, and how hiring runs.
*
* NO TAILWIND. The four section frames are `components/marketing/band`'s `Band`
* and `Head`; @hanzo/ui's marketing components carry the type and the controls
* (`Display`, `Lede`, `Title`, `Chip`, `Action`, `Leaf`, `Line`); everything
* left is gui props over @hanzo/design's tokens.
*/
import { useState, useEffect, type FormEvent } from "react"
import { motion } from "@/components/motion"
import {
Briefcase,
Globe,
Clock,
MapPin,
Users,
Sparkles,
ArrowRight,
Heart,
CheckCircle2,
X,
Share2,
Check,
ExternalLink,
} from "lucide-react"
import { Box, Button, Dialog, DialogContent, DialogTitle, Input, Text, Textarea, View, XStack, YStack } from '@hanzo/ui'
import { Grid } from '@hanzo/ui/grid'
import { Band, Head } from '@/components/marketing/band'
import { Action, Chip, Display, Lede, Title, Leaf, Lift, Line, type LineProps } from '@hanzo/ui/marketing'
import { api } from '@hanzo/app/lib/api'
import { track } from '@hanzo/app/lib/tags'
import { jobOpenings, getJobOpening, type JobOpening } from '@/lib/careers'
import { shownCareer } from '@/lib/launch'
import { ResumeAndConsent, resumeProblem, uploadResume } from './apply'
/** The two inks this page draws body copy in. */
const INK = 'var(--foreground)'
const DIM = 'var(--muted-foreground)'
/** The pair of controls that closes a section, wrapping on a phone. */
const ROW = { flexWrap: 'wrap', items: 'center', justify: 'center', gap: 16 } as const
/** The hairline tile, centred. */
const CARD = { rounded: 'var(--radius-xl)', borderWidth: 1, borderColor: 'var(--border)', bg: 'var(--secondary)', p: 24 } as const
/** A card's heading and the paragraph under it. */
const CardTitle = (p: LineProps) => (
<Line render="h3" display="block" mb={8} fontSize="$4" lineHeight="1.5556" fontWeight="600" color={INK} {...p} />
)
const CardBody = (p: LineProps) => (
<Line render="p" display="block" fontSize="$2" lineHeight="1.4286" color={DIM} {...p} />
)
/** A job card's own frame: `Leaf` with its edge drawn at rest and 24px inside. */
const OPENING = { p: 24, borderColor: "var(--border)", bg: "var(--secondary)" } as const
/** An icon on a tinted tile — the mark that opens a card. */
const TILE = {
width: 48,
height: 48,
items: 'center',
justify: 'center',
rounded: 'var(--radius-lg)',
'$platform-web': { backgroundColor: 'color-mix(in oklab, var(--pure-white) 10%, transparent)' },
} as const
/** The one fact line beside a job: a mark and a word. */
const Fact = (p: LineProps) => (
<Line display="inline-flex" items="center" gap={4} whiteSpace="normal" fontSize="$2" lineHeight="1.4286" color={DIM} {...p} />
)
const benefits = [
{ icon: Globe, title: "Remote-first", description: "The team is distributed. Work from wherever you already live." },
{ icon: Clock, title: "Your own hours", description: "We care what you ship, not what time you were online." },
{ icon: Users, title: "Small team", description: "Few enough people that you own whole systems rather than tickets." },
{ icon: Sparkles, title: "The work is public", description: "Most of what we build is open source, under your own name." },
]
const hiringSteps = [
{ step: "1", title: "Application Review", description: "We review your resume and application materials" },
{ step: "2", title: "Initial Interview", description: "Get to know you and your experience" },
{ step: "3", title: "Technical Assessment", description: "Showcase your skills (no whiteboarding)" },
{ step: "4", title: "Final Interview", description: "Meet the team and discuss next steps" },
]
/** An address as https: one typed without a scheme gets https://, and cloud drops any other. */
const https = (u: string): string => {
const t = u.trim()
return !t || /^[a-z][a-z0-9+.-]*:/i.test(t) ? t : `https://${t}`
}
export default function CareersPage() {
const [activeJob, setActiveJob] = useState<JobOpening | null>(null)
const [copiedId, setCopiedId] = useState<string | null>(null)
const [form, setForm] = useState({
name: '',
email: '',
github: '',
linkedin: '',
location: '',
resume: '',
notes: '',
})
const [file, setFile] = useState<File | null>(null)
const [consent, setConsent] = useState(false)
const [busy, setBusy] = useState(false)
const [sent, setSent] = useState(false)
const [wrong, setWrong] = useState<string | null>(null)
useEffect(() => {
if (typeof window === 'undefined') return
const params = new URLSearchParams(window.location.search)
const applyId = params.get('apply')
if (applyId) {
const match = getJobOpening(applyId)
if (match) setActiveJob(match)
}
}, [])
const openApply = (job: JobOpening) => {
setActiveJob(job)
setSent(false)
setWrong(null)
if (typeof window !== 'undefined') {
history.pushState(null, '', `?apply=${job.id}`)
}
}
const closeApply = () => {
setActiveJob(null)
setSent(false)
setWrong(null)
if (typeof window !== 'undefined') {
const url = new URL(window.location.href)
url.searchParams.delete('apply')
history.pushState(null, '', url.pathname + (url.hash || ''))
}
}
const copyRoleLink = (jobId: string, e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
if (typeof window !== 'undefined') {
const origin = window.location.origin
navigator.clipboard.writeText(`${origin}/careers/${jobId}`)
setCopiedId(jobId)
setTimeout(() => setCopiedId(null), 2000)
}
}
const handleSubmit = async (e: FormEvent) => {
e.preventDefault()
if (busy) return
if (!form.name.trim() || !form.email.trim() || !form.notes.trim()) {
setWrong('Please fill in your name, email, and cover note / background.')
return
}
const EMAIL_TEST = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!EMAIL_TEST.test(form.email.trim())) {
setWrong('Please enter a valid email address.')
return
}
if (file && resumeProblem(file)) {
setWrong(resumeProblem(file))
return
}
setWrong(null)
setBusy(true)
let resumeFile = ''
try {
if (file) resumeFile = await uploadResume(file)
} catch {
setWrong('Your resume did not upload. Please try again, or give a link instead.')
setBusy(false)
return
}
const payload = {
name: form.name.trim(),
email: form.email.trim(),
role: activeJob?.title || 'Open Application',
department: activeJob?.department || 'General',
country: form.location.trim() || activeJob?.location || 'Remote',
source: `hanzo.ai/careers/${activeJob?.id || 'open'}`,
// An application to an opening is a candidate in the CRM (cloud apps/marketing
// leads.go `job`): what the person wrote, their resume and their links, with no
// call offered and nothing sent to the ad platforms.
job: activeJob?.id || 'open',
need: form.notes.trim(),
resume: https(form.resume),
links: [https(form.github), https(form.linkedin)].filter(Boolean),
resume_file: resumeFile,
consent,
}
try {
const r = await fetch(`${api()}/v1/marketing/leads`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
if (!r.ok) throw new Error(`HTTP ${r.status}`)
track('career_application_submitted', { role: payload.role, department: payload.department, slug: activeJob?.id })
setSent(true)
} catch (err) {
track('career_application_submitted', { role: payload.role, department: payload.department, slug: activeJob?.id, error: String(err) })
setWrong('Your application did not reach us. Please try again, or email it to [email protected].')
} finally {
setBusy(false)
}
}
return (
<Box minH="100vh" $platform-web={{ color: INK }}>
<main>
{/* Hero Section */}
<Box
render="section"
position="relative"
overflow="hidden"
pt={96}
pb={64}
px={16}
$md={{ px: 32 }}
$lg={{ px: 48 }}
>
<View
aria-hidden
position="absolute"
t={0}
l="50%"
x="-50%"
width={800}
height={400}
backgroundImage="radial-gradient(circle, color-mix(in srgb, var(--primary) 12%, transparent) 0%, transparent 70%)"
filter="blur(80px)"
pointerEvents="none"
/>
<Box position="relative" z="var(--z-raised)" width="100%" maxW={1024} mx="auto">
<Box $platform-web={{ textAlign: 'center' }}>
<Chip render={<motion.div initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.4 }} />} mb={24} px={12} py={4} fontSize="$1" lineHeight="1.3333" fontWeight="500" borderColor="var(--border)" bg="color-mix(in oklab, var(--pure-white) 20%, transparent)" color={INK}>
<Heart width={14} height={14} />
Careers
</Chip>
<Display render={<motion.h1 initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.4, delay: 0.05 }} />} mb={24}>
Compilers, cryptography,<br />
and the cloud they run on.
</Display>
<Lede render={<motion.p initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.4, delay: 0.1 }} />} mb={40} width="100%" maxW={768} mx="auto">
Hanzo is a small team building an open AI cloud — the inference engine, the models, the backend services, and the agents that use them. Most of what we write is public, so you can read the codebase before you apply.
</Lede>
<XStack render={<motion.div initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.4, delay: 0.15 }} />} {...ROW}>
<Action href="#open-positions" fill>
View Open Positions
<ArrowRight width={16} height={16} />
</Action>
<Action href="/about">
Read the history
</Action>
</XStack>
</Box>
</Box>
</Box>
{/* Benefits Section */}
<Band rule={false} pad="$10" measure={1152} ground="color-mix(in oklab, var(--secondary) 20%, transparent)">
<Head title="Benefits & Perks" lede="How the team actually works." />
<Grid columns={{ min: 260, max: 4 }} gap={24}>
{benefits.map((benefit, index) => {
const Icon = benefit.icon
return (
<Box
key={benefit.title}
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ delay: index * 0.1 }} />}
{...CARD}
$platform-web={{ textAlign: 'center' }}
>
<XStack mb={16} mx="auto" {...TILE}>
<Icon width={24} height={24} color={INK} />
</XStack>
<CardTitle>{benefit.title}</CardTitle>
<CardBody>{benefit.description}</CardBody>
</Box>
)
})}
</Grid>
</Band>
{/* Open Positions Section */}
<Band id="open-positions" rule={false} pad="$10" measure={1152}>
<Head title="Open Positions" lede="Remote, unless the work needs hardware in a room." />
<Grid columns={{ min: 320, max: 2 }} gap={24}>
{jobOpenings.filter((job) => shownCareer(job.id)).map((job, index) => (
<Leaf
id={job.id}
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ delay: index * 0.05 }} />}
key={job.id}
{...OPENING}
>
<XStack items="flex-start" gap={16}>
<XStack shrink={0} {...TILE}>
<Briefcase width={24} height={24} color={INK} />
</XStack>
<YStack grow={1} shrink={1} flexBasis="0%">
<XStack items="center" justify="space-between" mb={8} gap={8}>
<Line href={`/careers/${job.id}`} color="inherit" whiteSpace="inherit">
<Lift render="h3" display="block" fontSize="$6" lineHeight="1.4" fontWeight="700">
{job.title}
</Lift>
</Line>
<Line
render="button"
type="button"
onClick={(e) => copyRoleLink(job.id, e)}
title="Copy direct link to this position"
display="inline-flex"
items="center"
p={4}
color={copiedId === job.id ? 'var(--primary)' : DIM}
>
{copiedId === job.id ? <Check size={16} /> : <Share2 size={16} />}
</Line>
</XStack>
<XStack gap={12} mb={12} flexWrap="wrap">
<Fact><MapPin width={16} height={16} /> {job.location}</Fact>
<Fact><Clock width={16} height={16} /> {job.type}</Fact>
<Fact><Users width={16} height={16} /> {job.department}</Fact>
</XStack>
<CardBody mb={16}>{job.description}</CardBody>
<XStack gap={12} flexWrap="wrap" items="center">
<Action
href={`/careers/${job.id}`}
onClick={(e) => {
e.preventDefault()
openApply(job)
}}
fill
self="flex-start"
>
Apply for this role
<ArrowRight width={16} height={16} />
</Action>
<Action
href={`/careers/${job.id}`}
self="flex-start"
>
View Details
<ExternalLink width={14} height={14} />
</Action>
</XStack>
</YStack>
</XStack>
</Leaf>
))}
</Grid>
<Box render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} />} mt={32} $platform-web={{ textAlign: 'center' }}>
<Line render="p" display="block" mb={16} color={DIM}>
Don&apos;t see a position that fits your skills?
</Line>
<Action
href="/careers/open"
onClick={(e) => {
e.preventDefault()
const openRole = getJobOpening('open')
if (openRole) openApply(openRole)
}}
>
Submit Open Application
</Action>
</Box>
</Band>
{/* Hiring Process Section */}
<Band rule={false} pad="$10" measure={896} ground="color-mix(in oklab, var(--secondary) 20%, transparent)">
<Head title="Our Hiring Process" lede="No whiteboarding. Here is the whole thing." />
<Grid columns={{ min: 180, max: 4 }} gap={24}>
{hiringSteps.map((step, index) => (
<Box
key={step.step}
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ delay: index * 0.1 }} />}
$platform-web={{ textAlign: 'center' }}
>
<XStack
mb={16}
mx="auto"
{...TILE}
rounded="var(--radius-full)"
$platform-web={{ backgroundColor: 'color-mix(in oklab, var(--pure-white) 20%, transparent)' }}
>
<Line fontWeight="700" color={INK}>
{step.step}
</Line>
</XStack>
<CardTitle>{step.title}</CardTitle>
<CardBody>{step.description}</CardBody>
</Box>
))}
</Grid>
</Band>
{/* CTA Section */}
<Band rule={false} pad="$12" measure={896}>
<View
position="absolute"
t={-160}
r={-160}
width={320}
height={320}
rounded="var(--radius-full)"
filter="blur(64px)"
pointerEvents="none"
$platform-web={{ backgroundColor: 'color-mix(in oklab, var(--pure-white) 10%, transparent)' }}
/>
<View
position="absolute"
b={-160}
l={-160}
width={320}
height={320}
rounded="var(--radius-full)"
filter="blur(64px)"
pointerEvents="none"
$platform-web={{ backgroundColor: 'color-mix(in oklab, var(--pure-white) 5%, transparent)' }}
/>
<Box position="relative" z="var(--z-raised)" $platform-web={{ textAlign: 'center' }}>
<Title render={<motion.h2 initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} />} quiet mb={16}>Ready to join us?</Title>
<Lede render={<motion.p initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ delay: 0.1 }} />} mb={40} width="100%" maxW={672} mx="auto" mt="$3.5">
If you have read the codebase and had opinions about it, we want to hear them.
</Lede>
<XStack render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ delay: 0.2 }} />} {...ROW}>
<Action href="#open-positions" fill>
Browse Open Positions
<ArrowRight width={20} height={20} />
</Action>
<Action href="mailto:[email protected]">
careers@hanzo.ai
</Action>
</XStack>
</Box>
</Band>
<Dialog open={Boolean(activeJob)} onOpenChange={(o) => (!o ? closeApply() : undefined)}>
<DialogContent
showCloseButton={false}
width="calc(100vw - 32px)"
maxW={540}
rounded="$6"
p="$5"
gap="$4"
bg="var(--secondary)"
borderWidth={1}
borderColor="var(--border)"
>
<XStack items="center" justify="space-between" width="100%">
<YStack gap="$1">
<DialogTitle fontSize="$6" fontWeight="700" color={INK}>
{sent ? 'Application Received' : activeJob?.title}
</DialogTitle>
{!sent && activeJob ? (
<Text fontSize="$2" color={DIM}>
{activeJob.department} · {activeJob.location} · {activeJob.type}
</Text>
) : null}
</YStack>
<XStack
render="button"
aria-label="Close"
p="$1.5"
rounded="$3"
hoverStyle={{ bg: 'var(--white-06)' }}
cursor="pointer"
onPress={closeApply}
>
<X size={18} color={INK} />
</XStack>
</XStack>
{sent ? (
<YStack gap="$4" py="$4" items="center">
<CheckCircle2 size={48} color="var(--primary)" />
<YStack gap="$2" items="center">
<Text fontSize="$4" fontWeight="600" color={INK}>
Thank you for applying!
</Text>
<Text fontSize="$2" color={DIM} maxW={420} $platform-web={{ textAlign: 'center' }}>
Your application for <Text fontWeight="600" color={INK}>{activeJob?.title}</Text> has been submitted to our team. We review submissions promptly and will reach out to <Text fontWeight="600" color={INK}>{form.email}</Text>.
</Text>
<Text fontSize="$1" color={DIM} mt="$2" $platform-web={{ textAlign: 'center' }}>
You can also email additional materials or portfolio samples directly to{' '}
<Text render="a" {...{ href: `mailto:[email protected]?subject=${encodeURIComponent(`Application: ${activeJob?.title} - ${form.name}`)}` }} color="var(--primary)" textDecorationLine="underline">
careers@hanzo.ai
</Text>.
</Text>
</YStack>
<Button variant="primary" onPress={closeApply} mt="$2">
Done
</Button>
</YStack>
) : (
<YStack render="form" {...{ onSubmit: handleSubmit }} width="100%" gap={14}>
<YStack gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
Full Name <Text render="span" color="var(--destructive)">*</Text>
</Text>
<Input
value={form.name}
onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
placeholder="Ada Lovelace"
required
/>
</YStack>
<YStack gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
Work Email <Text render="span" color="var(--destructive)">*</Text>
</Text>
<Input
type="email"
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
placeholder="[email protected]"
required
/>
</YStack>
<XStack gap="$3" flexWrap="wrap">
<YStack flex={1} minW={200} gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
GitHub / Portfolio
</Text>
<Input
value={form.github}
onChange={(e) => setForm((f) => ({ ...f, github: e.target.value }))}
placeholder="https://github.com/..."
/>
</YStack>
<YStack flex={1} minW={200} gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
LinkedIn / Website
</Text>
<Input
value={form.linkedin}
onChange={(e) => setForm((f) => ({ ...f, linkedin: e.target.value }))}
placeholder="https://linkedin.com/in/..."
/>
</YStack>
</XStack>
<YStack gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
Resume link
</Text>
<Input
value={form.resume}
onChange={(e) => setForm((f) => ({ ...f, resume: e.target.value }))}
placeholder="A link to your resume: PDF, Google Drive or Dropbox"
/>
</YStack>
<ResumeAndConsent file={file} onFile={setFile} consent={consent} onConsent={setConsent} />
<YStack gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
Location / Timezone
</Text>
<Input
value={form.location}
onChange={(e) => setForm((f) => ({ ...f, location: e.target.value }))}
placeholder="e.g. San Francisco, CA or Remote (UTC-8)"
/>
</YStack>
<YStack gap="$1">
<Text fontSize="$2" fontWeight="500" color={INK}>
Background & Why Hanzo <Text render="span" color="var(--destructive)">*</Text>
</Text>
<Textarea
value={form.notes}
onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
placeholder="Briefly tell us what systems you've built, open source work, or what interests you about our cloud and models."
rows={4}
required
/>
</YStack>
{wrong ? (
<Text fontSize="$2" color="var(--destructive)">
{wrong}
</Text>
) : null}
<XStack justify="space-between" items="center" mt="$2">
<Text
render="a"
{...{ href: `mailto:[email protected]?subject=${encodeURIComponent(`Application: ${activeJob?.title}`)}` }}
fontSize="$1"
color="var(--muted-foreground)"
textDecorationLine="underline"
>
Or email resume directly
</Text>
<XStack gap="$2">
<Button variant="ghost" size="sm" type="button" onPress={closeApply}>
Cancel
</Button>
<Button variant="primary" size="sm" type="submit" disabled={busy}>
{busy ? 'Submitting…' : 'Submit Application'}
</Button>
</XStack>
</XStack>
</YStack>
)}
</DialogContent>
</Dialog>
</main>
</Box>
)
}