diff --git a/apps/www/lib/careers.ts b/apps/www/lib/careers.ts new file mode 100644 index 00000000000..51b022ea1de --- /dev/null +++ b/apps/www/lib/careers.ts @@ -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 + ) +} diff --git a/apps/www/pages/careers.tsx b/apps/www/pages/careers.tsx index 70e68fcb283..05085155582 100644 --- a/apps/www/pages/careers.tsx +++ b/apps/www/pages/careers.tsx @@ -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 + placeholderJob: JobItemProps + contributors: { login: string; avatar_url: string; html_url: string }[] +} + +const CareerPage: NextPage = ({ jobs, placeholderJob, contributors }) => { const { basePath } = useRouter() const meta_title = 'Careers | Supabase' @@ -99,412 +110,400 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => { }} /> -
-
-

- Supabase Careers -

-

- We're on a mission to build the best developer platform -

-

- Explore remote possibilities and join our team to help us achieve it. -

- -
+
+

+ Supabase Careers +

+

+ We're on a mission to build the best developer platform +

+

+ Explore remote possibilities and join our team to help us achieve it. +

+ +
- -
- {career.company.map((company: { number: string; text: string }, i: number) => { - return ( -
-
-

- {company.number} -

- - {company.text} - -
- ) - })} -
-
- -
-
- + +
+ {career.company.map((company: { number: string; text: string }, i: number) => { + return (
+
+

{company.number}

+ + {company.text} + +
+ ) + })} +
+
+ +
+
+ +
- -
-
-

- We work together, wherever we are -

-

- 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. -

-
-
-

- We deeply believe in the efficacy of collaborative open source -

-
-
-
- - -
-
-
-

- What is Supabase -

-

- 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. -

-
-
-
- team photo -
-
-
-
-
- team photo -
-
-
-
-
-
-
- team photo -
-
-
-
-
- team photo -
-
-
-
- team photo -
-
-
-
-
- team photo -
-
-
-
-
- - -

- Human powered + > + +

+
+

+ We work together, wherever we are

-

- As a completely remote and asynchronous team, we focus on these five traits to - keep our team effective: +

+ 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.

-
- {career.humanPowered.map( - (human: { icon: string; title: string; text: string }, i: number) => { - return ( -
-
-

{human.title}

-

{human.text}

-
-
- ) - } - )} -
- - - -
-

- 1,000 + Contributors building Supabase +
+
+

+ We deeply believe in the efficacy of collaborative open source

-

- 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. -

-
- {contributors.map((contributor: any, i: number) => { - return ( -
- -
- {`${contributor.login} -
- -
- ) - })} -
-
-
-
-
-
-
-
-
-
-
-
-
- -

-
- - -
-
-

- Great people deserve great benefits -

-
- {career.benefits.map( - (benefits: { icon: string; title: string; text: string }, i: number) => { - return ( -
-
-

{benefits.title}

- - {benefits.text} - -
-
- ) - } - )} -
-
-
+ - -
-

How we hire

-

- 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. -

-
-
- {career.hiring.map((hiring: { title: string; text: string }, i: number) => { - return ( -
-
-

- {i + 1} -

-
-
-
-

- {hiring.title} -

-

- {hiring.text} -

+ +
+
+
+

+ What is Supabase +

+

+ 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. +

+
+
+
+ team photo
- ) - })} -

- -

-
- +
+
+
+ team photo +
+
+
+
+
+
+
+ team photo +
+
+
+
+
+ team photo +
+
+
+
+ team photo +
+
+
+
+
+ team photo +
+
+
+
+ - - -
-

- Open positions -

-

- Want to build the best developer platform? -
We’d love to talk to you. +

Human powered

+

+ As a completely remote and asynchronous team, we focus on these five traits to keep + our team effective:

-
- {jobs.map( - ( - job: { - title: string - location: any - employment: string - description: string - absolute_url: string - }, - i: number - ) => { +
+ {career.humanPowered.map( + (human: { icon: string; title: string; text: string }, i: number) => { return ( - -

- {job.title} -

-
-
- - - - {job.location.name} - - {job.employment} -
-

{job.description}

-
- Apply for position -
+
+
+

{human.title}

+

{human.text}

- +
) } )}
+ + +
+

+ 1,000 + Contributors building Supabase +

+

+ 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. +

+
+
+ {contributors.map((contributor: any, i: number) => { + return ( +
+ +
+ {`${contributor.login} +
+ +
+ ) + })} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+

+ Great people deserve great benefits +

+
+
+ {career.benefits.map( + (benefits: { icon: string; title: string; text: string }, i: number) => { + return ( +
+
+

{benefits.title}

+ + {benefits.text} + +
+
+ ) + } + )} +
+
+
+ + +
+

How we hire

+

+ 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. +

+
+
+ {career.hiring.map((hiring: { title: string; text: string }, i: number) => { + return ( +
+
+

+ {i + 1} +

+
+
+
+

+ {hiring.title} +

+

+ {hiring.text} +

+
+
+ ) + })} +

+ +

+
+
+ + + +
+ +

+ Open positions +

+

+ Want to build the best developer platform? +
We’d love to talk to you. +

+
+ {Object.entries(jobs).map(([team, teamJobs]) => ( +
+

{team}

+
+ {(teamJobs as JobItemProps[]) + .filter((job: any) => !filterGenericJob(job)) + .map((job: JobItemProps) => ( + + ))} +
+
+ ))} +
+
+ {placeholderJob && } +
+
+
) } +const JobItem: React.FC<{ job: JobItemProps }> = ({ job }) => { + const isPlaceholderJob = job.id === PLACEHOLDER_JOB_ID + + return ( + +

{job.title}

+
+
+ + + {job.location} + + {job.employment} +
+
+ {isPlaceholderJob ? 'Submit resume' : 'Apply for position'} +
+
+ + ) +} + export default CareerPage