feat: careers ATS switch [DON'T MERGE] (#29283)

* switch careers ATS

* clean up careers page
This commit is contained in:
Francesco Sansalvadore authored and GitHub committed 2024-10-01 17:28:32 +02:00
1 parent eba13666e2
commit f8cb082150
2 files changed
+407 -384

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
export interface JobItemProps {
id: string
title: string
location: any
team: string
employment: string
descriptionHtml: string
jobUrl: string
}
export const PLACEHOLDER_JOB_ID = '64d76968-1fe1-458c-8c6d-8859168c3fb7'
export const filterGenericJob = (job: JobItemProps) => job.id === PLACEHOLDER_JOB_ID
export const groupJobsByTeam = (jobs: JobItemProps[]) => {
return jobs.reduce(
(acc, job) => {
if (!acc[job.team]) {
acc[job.team] = []
}
acc[job.team].push(job)
return acc
},
{} as Record<string, JobItemProps[]>
)
}
+383 -384
View File
@@ -1,22 +1,26 @@
import { GlobeAltIcon } from '@heroicons/react/outline'
import { Check } from 'lucide-react'
import { NextPage } from 'next'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import ReactMarkdown from 'react-markdown'
import { NextSeo } from 'next-seo'
import { GlobeAltIcon } from '@heroicons/react/outline'
import { Check } from 'lucide-react'
import { Badge, Button, Separator, buttonVariants, cn } from 'ui'
import ReactMarkdown from 'react-markdown'
import Styles from '~/styles/career.module.css'
import Globe from '~/components/Globe'
import DefaultLayout from '~/components/Layouts/Default'
import SectionContainer from '~/components/Layouts/SectionContainer'
import { groupJobsByTeam, filterGenericJob, JobItemProps, PLACEHOLDER_JOB_ID } from '~/lib/careers'
import career from '~/data/career.json'
import Styles from '~/styles/career.module.css'
export async function getStaticProps() {
const job_res = await fetch('https://boards-api.greenhouse.io/v1/boards/supabase/jobs')
const job_res = await fetch('https://api.ashbyhq.com/posting-api/job-board/supabase')
const job_data = await job_res.json()
const jobs = groupJobsByTeam(job_data.jobs.filter((job: JobItemProps) => !filterGenericJob(job)))
const placeholderJob = job_data.jobs.find(filterGenericJob)
const contributor_res = await fetch(
'https://api.github.com/repos/supabase/supabase/contributors?per_page=100'
@@ -70,13 +74,20 @@ export async function getStaticProps() {
return {
props: {
jobs: job_data.jobs,
jobs,
placeholderJob,
contributors: contributors,
},
}
}
const CareerPage: NextPage = ({ jobs, contributors }: any) => {
interface CareersPageProps {
jobs: Record<string, JobItemProps[]>
placeholderJob: JobItemProps
contributors: { login: string; avatar_url: string; html_url: string }[]
}
const CareerPage: NextPage<CareersPageProps> = ({ jobs, placeholderJob, contributors }) => {
const { basePath } = useRouter()
const meta_title = 'Careers | Supabase'
@@ -99,412 +110,400 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
}}
/>
<DefaultLayout>
<div className="text-foreground">
<div className="container relative mx-auto px-6 py-10 lg:pt-12 lg:px-16 xl:px-20 text-center space-y-4">
<h1 className="text-sm text-brand md:text-base">
<span className="sr-only">Supabase </span>Careers
</h1>
<h2 className="text-3xl md:text-4xl xl:text-5xl lg:max-w-2xl xl:max-w-3xl lg:mx-auto tracking-[-1.5px]">
We're on a mission to build the best developer platform
</h2>
<p className="text-sm md:text-base text-foreground-lighter max-w-sm sm:max-w-md md:max-w-lg mx-auto">
Explore remote possibilities and join our team to help us achieve it.
</p>
<div className="mt-4">
<a href="#positions">
<Button type="primary">Open positions</Button>
</a>
</div>
</div>
<header className="container relative mx-auto px-6 pt-12 pb-8 lg:pt-24 lg:px-16 xl:px-20 text-center space-y-4">
<h1 className="text-sm text-brand md:text-base">
<span className="sr-only">Supabase </span>Careers
</h1>
<h2 className="text-3xl md:text-4xl xl:text-5xl lg:max-w-2xl xl:max-w-3xl lg:mx-auto tracking-[-1.5px]">
We're on a mission to build the best developer platform
</h2>
<p className="text-sm md:text-base text-foreground-lighter max-w-sm sm:max-w-md md:max-w-lg mx-auto">
Explore remote possibilities and join our team to help us achieve it.
</p>
<Button asChild type="primary" className="mt-4">
<Link href="#positions">Open positions</Link>
</Button>
</header>
<SectionContainer>
<div className="flex flex-wrap md:flex-nowrap -mt-6 md:mt-0 w-fit md:w-full mx-auto md:flex md:items-start justify-around lg:w-full lg:max-w-5xl">
{career.company.map((company: { number: string; text: string }, i: number) => {
return (
<div
key={i}
className="border-t-[1px] mt-6 mx-2 md:mx-2 md:mt-0 md:border-0 border-brand w-[134px] md:max-w-none"
>
<div className="hidden md:block border-t-[1px] lg:border-t-2 border-brand w-[60px] lg:w-[100px]"></div>
<h2 className="text-3xl lg:text-4xl pt-3 tracking-[-1.5px]">
{company.number}
</h2>
<ReactMarkdown className="text-foreground-light text-sm lg:text-base">
{company.text}
</ReactMarkdown>
</div>
)
})}
</div>
</SectionContainer>
<div className="py-[1.25px] bg-gradient-to-r from-background via-border to-background">
<div className="bg-alternative overflow-clip">
<SectionContainer className="md:!pt-16 md:grid md:max-h-[500px] grid-cols-1 md:grid-cols-5 md:gap-8">
<SectionContainer className="!pt-8">
<div className="flex flex-wrap md:flex-nowrap -mt-6 md:mt-0 w-fit md:w-full mx-auto md:flex md:items-start justify-around lg:w-full lg:max-w-5xl">
{career.company.map((company: { number: string; text: string }, i: number) => {
return (
<div
className="
key={i}
className="border-t-[1px] mt-6 mx-2 md:mx-2 md:mt-0 md:border-0 border-brand w-[134px] md:max-w-none"
>
<div className="hidden md:block border-t-[1px] lg:border-t-2 border-brand w-[60px] lg:w-[100px]"></div>
<h2 className="text-3xl lg:text-4xl pt-3 tracking-[-1.5px]">{company.number}</h2>
<ReactMarkdown className="text-foreground-light text-sm lg:text-base">
{company.text}
</ReactMarkdown>
</div>
)
})}
</div>
</SectionContainer>
<div className="py-[1.25px] bg-gradient-to-r from-background via-border to-background">
<div className="bg-alternative overflow-clip">
<SectionContainer className="md:!pt-16 md:grid md:max-h-[500px] grid-cols-1 md:grid-cols-5 md:gap-8">
<div
className="
relative md:col-span-2 aspect-square
w-[calc(100%+100px)] md:w-[calc(100%+450px)] xl:w-[calc(100%+200px)]
-mb-[160px] md:mb-0
-top-[160px] md:-top-[200px] xl:-top-[210px]
-left-[100px] md:-left-[450px] xl:-left-[200px]
"
>
<Globe />
</div>
<div className="relative md:col-span-3">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[300px] md:max-w-xs tracking-[-1.5px]">
We work together, wherever we are
</h2>
<p className="text-foreground-light mt-4 text-xs sm:text-sm md:text-base md:w-full">
Working in a globally distributed team is rewarding but has its challenges. We
are across many different timezones, so we use tools like Notion, Slack, and
Discord to stay connected to our team, and our community.
</p>
<div className="max-w-[300px] sm:max-w-md md:max-w-md mt-20">
<div className="border-t-2 border-brand w-4/12"></div>
<h2 className="text-2xl sm:text-3xl md:text-4xl pt-2 tracking-[-1.5px]">
We deeply believe in the efficacy of collaborative open source
</h2>
</div>
</div>
</SectionContainer>
<SectionContainer className="-mt-16 md:mt-16">
<div className="md:flex md:gap-6">
<div className="md:w-1/2">
<div>
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">
What is Supabase
</h2>
<p className="text-foreground-light text-xs sm:text-sm lg:text-base pt-2 sm:max-w-md xl:max-w-lg">
Supabase is an open source Firebase alternative, built by developers for
developers. Supabase adds auth, realtime, storage, restful APIs, and edge
functions to Postgres without a single line of code. Supabase was
born-remote. Having a globally distributed, open source company is our
secret weapon to hiring top-tier talent.
</p>
</div>
<div className="md:w-full rounded-md mt-10 md:mt-36 lg:mt-40">
<div className="relative w-full aspect-[148/125]">
<Image
src="/images/career/1.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
<div className="grid justify-items-end">
<div className="w-full md:w-5/6 rounded-md mt-6">
<div className="relative w-full aspect-[29/22]">
<Image
src="/images/career/2.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
</div>
<div className="mt-6 md:mt-0 w-full md:w-1/2">
<div className="w-full rounded-md">
<div className="relative w-full aspect-[137/110]">
<Image
src="/images/career/3.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
<div className="flex gap-6 mt-6">
<div className="w-full rounded-md">
<div className="relative w-full aspect-[142/189]">
<Image
src="/images/career/4.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
<div className="w-full rounded-md">
<div className="relative w-full aspect-[142/189]">
<Image
src="/images/career/5.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
<div className="w-full rounded-md mt-6">
<div className="relative w-full aspect-[16/9]">
<Image
src="/images/career/6.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
</div>
</SectionContainer>
<SectionContainer>
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">
Human powered
>
<Globe />
</div>
<div className="relative md:col-span-3">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[300px] md:max-w-xs tracking-[-1.5px]">
We work together, wherever we are
</h2>
<p className="text-foreground-lighter text-xs sm:text-sm lg:text-base pt-3 sm:w-3/5 lg:max-w-sm">
As a completely remote and asynchronous team, we focus on these five traits to
keep our team effective:
<p className="text-foreground-light mt-4 text-xs sm:text-sm md:text-base md:w-full">
Working in a globally distributed team is rewarding but has its challenges. We are
across many different timezones, so we use tools like Notion, Slack, and Discord
to stay connected to our team, and our community.
</p>
<div className="grid pt-10 gap-8 grid-cols-2 md:grid-cols-3 lg:gap-16 lg:grid-cols-5">
{career.humanPowered.map(
(human: { icon: string; title: string; text: string }, i: number) => {
return (
<div key={i} className="flex flex-col gap-3">
<div>
<h2 className="text-base">{human.title}</h2>
<p className="text-foreground-light text-xs lg:text-sm">{human.text}</p>
</div>
</div>
)
}
)}
</div>
</SectionContainer>
<SectionContainer className="!pb-0">
<div className="text-center">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[300px] xl:max-w-none mx-auto tracking-[-1.5px]">
1,000 + Contributors building Supabase
<div className="max-w-[300px] sm:max-w-md md:max-w-md mt-20">
<div className="border-t-2 border-brand w-4/12"></div>
<h2 className="text-2xl sm:text-3xl md:text-4xl pt-2 tracking-[-1.5px]">
We deeply believe in the efficacy of collaborative open source
</h2>
<p className="text-foreground-light text-xs sm:text-sm lg:text-base sm:max-w-lg lg:max-w-2xl mx-auto pt-3">
We're building a community of communities, bringing together developers from
many different backgrounds, as well as new developers looking to get involved
with open source. We love celebrating everyone who contributes their time to the
Supabase mission.
</p>
</div>
<div className="w-[1080px] h-[370px] mx-auto sm:mt-10 md:mt-16 lg:mt-28 2xl:mt-60">
{contributors.map((contributor: any, i: number) => {
return (
<div
className={`${
Styles[`contributors-${i}`]
} absolute w-12 h-12 md:w-14 md:h-14 lg:w-16 lg:h-16 rounded-full border-[1.5px] border-default z-10
transition-all hover:scale-105 drop-shadow-sm hover:drop-shadow-md
`}
key={i}
>
<Link href={contributor.html_url} target="_blank">
<div className="relative w-full h-full">
<Image
src={contributor.avatar_url}
alt={`${contributor.login} github avatar`}
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-full object-cover"
draggable={false}
/>
</div>
</Link>
</div>
)
})}
<div
className={`${Styles['contributors-bg-circle']} w-[100%] lg:w-[80%] left-[0%] lg:left-[10%] -bottom-[30%] xs:-bottom-[36%] sm:-bottom-[52%] md:-bottom-[64%] lg:-bottom-[80%] xl:-bottom-[100%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[80%] lg:w-[60%] left-[10%] lg:left-[20%] -bottom-[25%] xs:-bottom-[30%] sm:-bottom-[44%] md:-bottom-[54%] lg:-bottom-[60%] xl:-bottom-[75%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[60%] lg:w-[40%] left-[20%] lg:left-[30%] -bottom-[20%] xs:-bottom-[25%] sm:-bottom-[38%] md:-bottom-[44%] lg:-bottom-[40%] xl:-bottom-[50%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[40%] lg:w-[20%] left-[30%] lg:left-[40%] -bottom-[15%] xs:-bottom-[19%] sm:-bottom-[30%] md:-bottom-[34%] lg:-bottom-[20%] xl:-bottom-[25%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
</div>
</SectionContainer>
</div>
</div>
<SectionContainer>
<div className="xl:flex lg:items-start xl:gap-10 justify-between">
<div className="xl:min-w-[300px] xl:max-w-[400px]">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[280px] sm:max-w-xs xl:max-w-none tracking-[-1.5px]">
Great people deserve great benefits
</h2>
</div>
<div className="mt-12 xl:mt-0 space-y-6 lg:space-y-0 sm:w-fit sm:mx-auto lg:grid lg:grid-cols-2 lg:gap-16">
{career.benefits.map(
(benefits: { icon: string; title: string; text: string }, i: number) => {
return (
<div className="h-full flex items-start space-x-6 w-full" key={i}>
<div className="h-fit text-sm lg:text-base">
<h2 className="text-sm">{benefits.title}</h2>
<ReactMarkdown className="prose pt-1 text-sm">
{benefits.text}
</ReactMarkdown>
</div>
</div>
)
}
)}
</div>
</div>
</SectionContainer>
</SectionContainer>
<SectionContainer>
<div className="text-center sm:max-w-md md:w-3/4 lg:max-w-lg xl:max-w-2xl mx-auto">
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">How we hire</h2>
<p className="text-xs sm:text-sm lg:text-base text-foreground-light pt-3">
The entire process is fully remote and all communication happens over email or via
video chat in Google Meet. The calls are all 1:1 and usually take between 20-45
minutes. We know you are interviewing us too, so please ask questions. We are happy
to answer.
</p>
</div>
<div className="mt-16 md:ml-36 lg:flex lg:items-start lg:w-fit lg:mx-auto">
{career.hiring.map((hiring: { title: string; text: string }, i: number) => {
return (
<div
key={i + 1}
className="flex lg:block items-start space-x-6 lg:space-x-0 lg:w-full"
>
<div className="lg:flex items-center">
<h3 className="bg-brand-400 border-[1px] border-brand-300 text-brand-600 text-md text-center w-[44px] px-2 py-1.5 rounded-md">
{i + 1}
</h3>
<div className="h-[100px] w-[1px] sm:h-[100px] mx-auto lg:h-[1px] lg:w-full bg-brand-500 lg:pr-6"></div>
</div>
<div className="lg:mt-6">
<h2 className="sm:text-lg max-w-[75%] xl:max-w-none xl:w-11/12 lg:max-w-none">
{hiring.title}
</h2>
<p className="text-foreground-light text-xs sm:text-sm mt-1 md:w-3/4 lg:w-11/12">
{hiring.text}
</p>
<SectionContainer className="-mt-16 md:mt-16">
<div className="md:flex md:gap-6">
<div className="md:w-1/2">
<div>
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">
What is Supabase
</h2>
<p className="text-foreground-light text-xs sm:text-sm lg:text-base pt-2 sm:max-w-md xl:max-w-lg">
Supabase is an open source Firebase alternative, built by developers for
developers. Supabase adds auth, realtime, storage, restful APIs, and edge
functions to Postgres without a single line of code. Supabase was born-remote.
Having a globally distributed, open source company is our secret weapon to
hiring top-tier talent.
</p>
</div>
<div className="md:w-full rounded-md mt-10 md:mt-36 lg:mt-40">
<div className="relative w-full aspect-[148/125]">
<Image
src="/images/career/1.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
)
})}
<h3 className="bg-brand-400 border-[1px] border-brand-300 text-brand-600 text-xl w-[44px] lg:min-w-[40px] min-h-[40px] px-2 py-1 rounded-md grid justify-items-center items-center">
<Check />
</h3>
</div>
</SectionContainer>
<div className="grid justify-items-end">
<div className="w-full md:w-5/6 rounded-md mt-6">
<div className="relative w-full aspect-[29/22]">
<Image
src="/images/career/2.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
</div>
<div className="mt-6 md:mt-0 w-full md:w-1/2">
<div className="w-full rounded-md">
<div className="relative w-full aspect-[137/110]">
<Image
src="/images/career/3.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
<div className="flex gap-6 mt-6">
<div className="w-full rounded-md">
<div className="relative w-full aspect-[142/189]">
<Image
src="/images/career/4.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
<div className="w-full rounded-md">
<div className="relative w-full aspect-[142/189]">
<Image
src="/images/career/5.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
<div className="w-full rounded-md mt-6">
<div className="relative w-full aspect-[16/9]">
<Image
src="/images/career/6.jpg"
alt="team photo"
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-md object-cover"
draggable={false}
/>
</div>
</div>
</div>
</div>
</SectionContainer>
<Separator />
<div id="positions" className="max-w-6xl mx-auto">
<SectionContainer>
<h2 className="text-xl sm:text-3xl xl:text-3xl tracking-[-1.5px] mb-3">
Open positions
</h2>
<p className="max-w-xl text-foreground-lighter">
Want to build the best developer platform?
<br /> We’d love to talk to you.
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">Human powered</h2>
<p className="text-foreground-lighter text-xs sm:text-sm lg:text-base pt-3 sm:w-3/5 lg:max-w-sm">
As a completely remote and asynchronous team, we focus on these five traits to keep
our team effective:
</p>
<div className="mt-10 -space-y-px">
{jobs.map(
(
job: {
title: string
location: any
employment: string
description: string
absolute_url: string
},
i: number
) => {
<div className="grid pt-10 gap-8 grid-cols-2 md:grid-cols-3 lg:gap-16 lg:grid-cols-5">
{career.humanPowered.map(
(human: { icon: string; title: string; text: string }, i: number) => {
return (
<Link
href={job.absolute_url}
key={i}
className="
first-of-type:rounded-t-md last-of-type:rounded-b-md
cursor-pointer md:cursor-default bg-surface-75 border border-muted drop-shadow-sm p-4 px-7
flex flex-col md:flex-row
md:items-center
transition hover:bg-surface-100
hover:cursor-pointer"
>
<h2 className="text-base min-w-[240px] lg:min-w-[316px] sm:truncate mr-6">
{job.title}
</h2>
<div className="flex justify-between justify-[normal] pt-2 md:pt-0 w-full items-center">
<div className="flex items-center space-x-4">
<Badge
className="bg-surface-200 bg-opacity-100 border-muted"
variant={'default'}
>
<GlobeAltIcon className="w-3 h-3" />
<span className="ml-1">{job.location.name}</span>
</Badge>
<span className="hidden md:block">{job.employment}</span>
</div>
<p className="hidden lg:block lg:text-sm">{job.description}</p>
<div
className={cn(
buttonVariants({ type: 'default', size: 'tiny' }),
'rounded-full'
)}
>
Apply for position
</div>
<div key={i} className="flex flex-col gap-3">
<div>
<h2 className="text-base">{human.title}</h2>
<p className="text-foreground-light text-xs lg:text-sm">{human.text}</p>
</div>
</Link>
</div>
)
}
)}
</div>
</SectionContainer>
<SectionContainer className="!pb-0">
<div className="text-center">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[300px] xl:max-w-none mx-auto tracking-[-1.5px]">
1,000 + Contributors building Supabase
</h2>
<p className="text-foreground-light text-xs sm:text-sm lg:text-base sm:max-w-lg lg:max-w-2xl mx-auto pt-3">
We're building a community of communities, bringing together developers from many
different backgrounds, as well as new developers looking to get involved with open
source. We love celebrating everyone who contributes their time to the Supabase
mission.
</p>
</div>
<div className="w-[1080px] h-[370px] mx-auto sm:mt-10 md:mt-16 lg:mt-28 2xl:mt-60">
{contributors.map((contributor: any, i: number) => {
return (
<div
className={`${
Styles[`contributors-${i}`]
} absolute w-12 h-12 md:w-14 md:h-14 lg:w-16 lg:h-16 rounded-full border-[1.5px] border-default z-10
transition-all hover:scale-105 drop-shadow-sm hover:drop-shadow-md
`}
key={i}
>
<Link href={contributor.html_url} target="_blank">
<div className="relative w-full h-full">
<Image
src={contributor.avatar_url}
alt={`${contributor.login} github avatar`}
fill
sizes="(min-width: 767px) 45vw, 100vw"
placeholder="blur"
blurDataURL="/images/blur.png"
className="rounded-full object-cover"
draggable={false}
/>
</div>
</Link>
</div>
)
})}
<div
className={`${Styles['contributors-bg-circle']} w-[100%] lg:w-[80%] left-[0%] lg:left-[10%] -bottom-[30%] xs:-bottom-[36%] sm:-bottom-[52%] md:-bottom-[64%] lg:-bottom-[80%] xl:-bottom-[100%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[80%] lg:w-[60%] left-[10%] lg:left-[20%] -bottom-[25%] xs:-bottom-[30%] sm:-bottom-[44%] md:-bottom-[54%] lg:-bottom-[60%] xl:-bottom-[75%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[60%] lg:w-[40%] left-[20%] lg:left-[30%] -bottom-[20%] xs:-bottom-[25%] sm:-bottom-[38%] md:-bottom-[44%] lg:-bottom-[40%] xl:-bottom-[50%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
<div
className={`${Styles['contributors-bg-circle']} w-[40%] lg:w-[20%] left-[30%] lg:left-[40%] -bottom-[15%] xs:-bottom-[19%] sm:-bottom-[30%] md:-bottom-[34%] lg:-bottom-[20%] xl:-bottom-[25%]`}
>
<div className="flex flex-col justify-between h-full bg-alternative rounded-full p-4"></div>
</div>
</div>
</SectionContainer>
</div>
</div>
<SectionContainer>
<div className="xl:flex lg:items-start xl:gap-10 justify-between">
<div className="xl:min-w-[300px] xl:max-w-[400px]">
<h2 className="text-2xl sm:text-3xl xl:text-4xl max-w-[280px] sm:max-w-xs xl:max-w-none tracking-[-1.5px]">
Great people deserve great benefits
</h2>
</div>
<div className="mt-12 xl:mt-0 space-y-6 lg:space-y-0 sm:w-fit sm:mx-auto lg:grid lg:grid-cols-2 lg:gap-16">
{career.benefits.map(
(benefits: { icon: string; title: string; text: string }, i: number) => {
return (
<div className="h-full flex items-start space-x-6 w-full" key={i}>
<div className="h-fit text-sm lg:text-base">
<h2 className="text-sm">{benefits.title}</h2>
<ReactMarkdown className="prose pt-1 text-sm">
{benefits.text}
</ReactMarkdown>
</div>
</div>
)
}
)}
</div>
</div>
</SectionContainer>
<SectionContainer>
<div className="text-center sm:max-w-md md:w-3/4 lg:max-w-lg xl:max-w-2xl mx-auto">
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-1.5px]">How we hire</h2>
<p className="text-xs sm:text-sm lg:text-base text-foreground-light pt-3">
The entire process is fully remote and all communication happens over email or via
video chat in Google Meet. The calls are all 1:1 and usually take between 20-45
minutes. We know you are interviewing us too, so please ask questions. We are happy to
answer.
</p>
</div>
<div className="mt-16 md:ml-36 lg:flex lg:items-start lg:w-fit lg:mx-auto">
{career.hiring.map((hiring: { title: string; text: string }, i: number) => {
return (
<div
key={i + 1}
className="flex lg:block items-start space-x-6 lg:space-x-0 lg:w-full"
>
<div className="lg:flex items-center">
<h3 className="bg-brand-400 border-[1px] border-brand-300 text-brand-600 text-md text-center w-[44px] px-2 py-1.5 rounded-md">
{i + 1}
</h3>
<div className="h-[100px] w-[1px] sm:h-[100px] mx-auto lg:h-[1px] lg:w-full bg-brand-500 lg:pr-6"></div>
</div>
<div className="lg:mt-6">
<h2 className="sm:text-lg max-w-[75%] xl:max-w-none xl:w-11/12 lg:max-w-none">
{hiring.title}
</h2>
<p className="text-foreground-light text-xs sm:text-sm mt-1 md:w-3/4 lg:w-11/12">
{hiring.text}
</p>
</div>
</div>
)
})}
<h3 className="bg-brand-400 border-[1px] border-brand-300 text-brand-600 text-xl w-[44px] lg:min-w-[40px] min-h-[40px] px-2 py-1 rounded-md grid justify-items-center items-center">
<Check />
</h3>
</div>
</SectionContainer>
<Separator />
<div id="positions" className="max-w-6xl mx-auto">
<SectionContainer>
<h2 className="text-xl sm:text-3xl xl:text-3xl tracking-[-1.5px] mb-3">
Open positions
</h2>
<p className="max-w-xl text-foreground-lighter">
Want to build the best developer platform?
<br /> We’d love to talk to you.
</p>
<div className="mt-10 flex flex-col gap-4">
{Object.entries(jobs).map(([team, teamJobs]) => (
<div key={team}>
<h4 className="text-foreground-lighter text-sm">{team}</h4>
<div className="mt-2 -space-y-px">
{(teamJobs as JobItemProps[])
.filter((job: any) => !filterGenericJob(job))
.map((job: JobItemProps) => (
<JobItem job={job} key={job.id} />
))}
</div>
</div>
))}
</div>
<div className="pt-4 mt-4 border-t border-muted -space-y-px">
{placeholderJob && <JobItem job={placeholderJob} />}
</div>
</SectionContainer>
</div>
</DefaultLayout>
</>
)
}
const JobItem: React.FC<{ job: JobItemProps }> = ({ job }) => {
const isPlaceholderJob = job.id === PLACEHOLDER_JOB_ID
return (
<Link
href={job.jobUrl}
className="
first-of-type:rounded-t-md last-of-type:rounded-b-md
cursor-pointer md:cursor-default bg-surface-75 border border-muted drop-shadow-sm p-4 px-7
flex flex-col md:flex-row
md:items-center
transition hover:bg-surface-100
hover:cursor-pointer
"
target="_blank"
>
<h2 className="text-base min-w-[240px] lg:min-w-[316px] sm:truncate mr-6">{job.title}</h2>
<div className="flex justify-between justify-[normal] pt-2 md:pt-0 w-full items-center">
<div className="flex items-center gap-4">
<Badge>
<GlobeAltIcon className="w-3 h-3" />
<span className="ml-1">{job.location}</span>
</Badge>
<span className="hidden md:block">{job.employment}</span>
</div>
<div className={cn(buttonVariants({ type: 'default', size: 'tiny' }), 'rounded-full')}>
{isPlaceholderJob ? 'Submit resume' : 'Apply for position'}
</div>
</div>
</Link>
)
}
export default CareerPage