diff --git a/.env.example b/.env.example index 751ad6b..d9e8d38 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,6 @@ GOOGLE_API_KEY= NOTION_TOKEN= +KEKA_CLIENT_ID= +KEKA_CLIENT_SECRET= +KEKA_API_KEY= +KEKA_COMPANY=procedure diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7a7895..0ba1c03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,10 @@ jobs: run: npm run build env: NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }} + KEKA_CLIENT_ID: ${{ secrets.KEKA_CLIENT_ID }} + KEKA_CLIENT_SECRET: ${{ secrets.KEKA_CLIENT_SECRET }} + KEKA_API_KEY: ${{ secrets.KEKA_API_KEY }} + KEKA_COMPANY: ${{ secrets.KEKA_COMPANY }} - name: Check bundle size run: npm run bundle:check diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index ef0547f..943d7e5 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -71,6 +71,10 @@ jobs: run: ${{ steps.detect-package-manager.outputs.runner }} next build env: NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }} + KEKA_CLIENT_ID: ${{ secrets.KEKA_CLIENT_ID }} + KEKA_CLIENT_SECRET: ${{ secrets.KEKA_CLIENT_SECRET }} + KEKA_API_KEY: ${{ secrets.KEKA_API_KEY }} + KEKA_COMPANY: ${{ secrets.KEKA_COMPANY }} - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/.github/workflows/rebuild-jobs.yml b/.github/workflows/rebuild-jobs.yml new file mode 100644 index 0000000..09d7b5b --- /dev/null +++ b/.github/workflows/rebuild-jobs.yml @@ -0,0 +1,23 @@ +name: Rebuild for Job Updates + +on: + schedule: + # Run twice daily at 6am and 6pm UTC + - cron: "0 6,18 * * *" + # Allow manual trigger + workflow_dispatch: + +jobs: + trigger-rebuild: + runs-on: ubuntu-latest + steps: + - name: Trigger Pages Deployment + uses: actions/github-script@v7 + with: + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'nextjs.yml', + ref: 'main', + }); diff --git a/app/careers/CareersClient.tsx b/app/careers/CareersClient.tsx new file mode 100644 index 0000000..9f8e01f --- /dev/null +++ b/app/careers/CareersClient.tsx @@ -0,0 +1,639 @@ +"use client"; + +import { motion } from "framer-motion"; +import Image from "next/image"; +import Link from "next/link"; +import { PageHero } from "@/components/ui"; +import { JobListings } from "@/components/careers"; +import type { JobListing } from "@/lib/keka-jobs"; + +interface CareersClientProps { + jobs: JobListing[]; + departments: string[]; +} + +// Benefits data +const benefits = [ + { + icon: ( + + + + ), + title: "100% Remote Positions", + description: + "Work from anywhere with a globally distributed team spanning 4 continents. Async-first communication means no mandatory meetings disrupting your focus time.", + }, + { + icon: ( + + + + ), + title: "Top-Tier Compensation", + description: + "Above-market salaries benchmarked against top tech companies, plus equity participation. We invest in talent that delivers enterprise-grade results.", + }, + { + icon: ( + + + + ), + title: "$3,000 Learning Budget", + description: + "Annual stipend for courses, conferences, and certifications. Stay current with AI advancements and earn credentials that accelerate your career trajectory.", + }, + { + icon: ( + + + + ), + title: "Comprehensive Health Coverage", + description: + "Full medical, dental, and vision insurance for you and your dependents. Plus a dedicated wellness stipend for gym memberships, mental health support, or whatever keeps you performing at your best.", + }, + { + icon: ( + + + + ), + title: "Unlimited PTO Policy", + description: + "Flexible time off with a minimum of 4 weeks encouraged annually. Sustainable performance requires genuine rest, and we trust senior professionals to manage their own schedules.", + }, + { + icon: ( + + + + ), + title: "Enterprise AI Projects", + description: + "Solve complex AI challenges for industry-leading clients. Direct access to cutting-edge models from OpenAI, Anthropic, and Google, plus the latest MLOps tooling and infrastructure.", + }, +]; + +// Values data +const values = [ + { + title: "Production-First Engineering", + description: + "Every system we build is designed for enterprise-scale production. Our engineers take pride in delivering AI solutions that handle millions of requests and meet the strictest SLAs.", + }, + { + title: "Continuous Technical Growth", + description: + "AI evolves rapidly, and so do we. Weekly knowledge sharing, dedicated learning time, and a culture of experimentation ensure you stay at the forefront of the industry. Our Best Workplace certification reflects this commitment to your growth.", + }, + { + title: "Direct, Transparent Communication", + description: + "We value candid feedback, thoughtful debate, and clear expectations. No politics or ambiguity, just honest collaboration focused on delivering exceptional results for our clients.", + }, + { + title: "Ownership and Accountability", + description: + "Senior engineers own their projects end-to-end. You will have the autonomy to make architectural decisions and the responsibility to deliver outcomes that drive real business impact.", + }, +]; + +export function CareersClient({ jobs, departments }: CareersClientProps) { + return ( +
+ {/* ============================================ + HERO SECTION + ============================================ */} + + {/* TSOW Certification Badge */} +
+ TSOW Certified Best Workplace +
+

+ Officially a TSOW Certified Best Workplace +

+

+ Recognized for creating a culture where people thrive. +

+
+
+
+ + {/* ============================================ + WHY JOIN US SECTION + ============================================ */} +
+ {/* Dot pattern */} +
+ +
+ +

+ Why Join Procedure +

+

+ Benefits Designed for Senior AI Engineers +

+

+ Competitive compensation, flexible remote work, and continuous + learning opportunities. Everything you need to do career-defining + work on enterprise AI projects. +

+
+ + {/* Benefits Grid */} +
+ {benefits.map((benefit, idx) => ( + + {/* Card glow effect */} +
+ +
+
+ {benefit.icon} +
+

+ {benefit.title} +

+

+ {benefit.description} +

+
+ + ))} +
+
+
+ + {/* ============================================ + OUR VALUES SECTION + ============================================ */} +
+ {/* Plus/cross pattern */} +
+ +
+ +

+ Our Engineering Culture +

+

+ The Values That Drive Our Work +

+

+ A certified best workplace culture built on trust, technical excellence, + and a shared commitment to delivering production AI systems that + transform enterprises. +

+
+ + {/* Values Grid */} +
+ {values.map((value, idx) => ( + + {/* Card glow effect */} +
+ +
+
+
+ {idx + 1} +
+
+

+ {value.title} +

+

+ {value.description} +

+
+
+
+ + ))} +
+
+
+ + {/* ============================================ + HIRING PROCESS SECTION + ============================================ */} +
+ {/* Dot pattern */} +
+ +
+ +

+ How We Hire +

+

+ Our Hiring Process +

+

+ A transparent and efficient process designed to identify + exceptional talent. From application to offer, we move quickly + while ensuring the right fit for both sides. +

+
+ + {/* Timeline - Desktop (Horizontal) */} +
+
+ {/* Connecting line */} +
+ +
+ {hiringSteps.map((item, idx) => ( + + {/* Step number circle */} +
+
+ {/* Glow effect */} +
+
+
{item.icon}
+
+
+
+ + {/* Card */} +
+
+
+
+ STEP {item.step} +
+

+ {item.title} +

+

+ {item.description} +

+
+
+ + ))} +
+
+
+ + {/* Timeline - Mobile (Vertical) */} +
+ {hiringSteps.map((item, idx) => ( + + {/* Timeline line */} + {idx < 4 && ( +
+ )} + + {/* Step number circle */} +
+
+
+
{item.icon}
+
+
+ + {/* Card */} +
+
+
+
+ STEP {item.step} +
+

+ {item.title} +

+

+ {item.description} +

+
+
+ + ))} +
+ + {/* Additional info */} + +

+ + Total timeline: 2-3 weeks. + {" "} + We value your time and move quickly through each stage. You will + have a dedicated point of contact throughout the process to answer + questions and provide updates. +

+
+
+
+ + {/* ============================================ + JOB OPENINGS SECTION + ============================================ */} +
+ {/* Hexagon pattern */} +
+ +
+ +

+ Current Openings +

+

+ Remote AI and Engineering Positions +

+

+ All roles are fully remote with global hiring. We support + engineers across every timezone and prioritize asynchronous + collaboration. +

+
+ + {/* Job Listings */} + + + +
+
+ + {/* ============================================ + CTA SECTION + ============================================ */} +
+ {/* Background gradient */} +
+ + {/* Accent orbs */} +
+
+ +
+ +

+ No Perfect Match? Let's Talk Anyway. +

+

+ Exceptional AI talent is rare, and we are always building our + pipeline. Submit your resume with a note about your ideal role, + and we will reach out when the right opportunity emerges. +

+ +
+ + Submit Your Application + + + + + + Learn About Procedure + +
+
+
+
+
+ ); +} + +// Hiring steps data (extracted to avoid duplication between desktop/mobile) +const hiringSteps = [ + { + step: 1, + title: "Application Received", + description: + "Submit your application through our careers portal. We review all applications within 3-5 business days.", + icon: ( + + + + ), + }, + { + step: 2, + title: "TA Screening", + description: + "Quick call with our Talent Acquisition team to discuss your experience, career goals, and role expectations.", + icon: ( + + + + ), + }, + { + step: 3, + title: "HM Screening", + description: + "Technical conversation with the Hiring Manager to explore your skills, project experience, and approach.", + icon: ( + + + + ), + }, + { + step: 4, + title: "Interviews", + description: + "Technical assessments and team conversations covering coding exercises, system design, and cultural fit.", + icon: ( + + + + ), + }, + { + step: 5, + title: "Offer Release", + description: + "Receive your offer with a detailed compensation breakdown. We move fast and keep the process transparent.", + icon: ( + + + + ), + }, +]; diff --git a/app/careers/page.tsx b/app/careers/page.tsx index 474d167..0107d6d 100644 --- a/app/careers/page.tsx +++ b/app/careers/page.tsx @@ -1,786 +1,14 @@ -"use client"; +import { getJobListings, getJobDepartments } from "@/lib/keka-jobs"; +import { CareersClient } from "./CareersClient"; -import { motion } from "framer-motion"; -import Image from "next/image"; -import Link from "next/link"; -import { PageHero } from "@/components/ui"; -import { KekaJobsEmbed } from "@/components/KekaJobsEmbed"; +export const dynamic = "force-static"; +export const revalidate = false; -// Benefits data -const benefits = [ - { - icon: ( - - - - ), - title: "100% Remote Positions", - description: - "Work from anywhere with a globally distributed team spanning 4 continents. Async-first communication means no mandatory meetings disrupting your focus time.", - }, - { - icon: ( - - - - ), - title: "Top-Tier Compensation", - description: - "Above-market salaries benchmarked against top tech companies, plus equity participation. We invest in talent that delivers enterprise-grade results.", - }, - { - icon: ( - - - - ), - title: "$3,000 Learning Budget", - description: - "Annual stipend for courses, conferences, and certifications. Stay current with AI advancements and earn credentials that accelerate your career trajectory.", - }, - { - icon: ( - - - - ), - title: "Comprehensive Health Coverage", - description: - "Full medical, dental, and vision insurance for you and your dependents. Plus a dedicated wellness stipend for gym memberships, mental health support, or whatever keeps you performing at your best.", - }, - { - icon: ( - - - - ), - title: "Unlimited PTO Policy", - description: - "Flexible time off with a minimum of 4 weeks encouraged annually. Sustainable performance requires genuine rest, and we trust senior professionals to manage their own schedules.", - }, - { - icon: ( - - - - ), - title: "Enterprise AI Projects", - description: - "Solve complex AI challenges for industry-leading clients. Direct access to cutting-edge models from OpenAI, Anthropic, and Google, plus the latest MLOps tooling and infrastructure.", - }, -]; +export default async function CareersPage() { + const [jobs, departments] = await Promise.all([ + getJobListings(), + getJobDepartments(), + ]); -// Values data -const values = [ - { - title: "Production-First Engineering", - description: - "Every system we build is designed for enterprise-scale production. Our engineers take pride in delivering AI solutions that handle millions of requests and meet the strictest SLAs.", - }, - { - title: "Continuous Technical Growth", - description: - "AI evolves rapidly, and so do we. Weekly knowledge sharing, dedicated learning time, and a culture of experimentation ensure you stay at the forefront of the industry. Our Best Workplace certification reflects this commitment to your growth.", - }, - { - title: "Direct, Transparent Communication", - description: - "We value candid feedback, thoughtful debate, and clear expectations. No politics or ambiguity, just honest collaboration focused on delivering exceptional results for our clients.", - }, - { - title: "Ownership and Accountability", - description: - "Senior engineers own their projects end-to-end. You will have the autonomy to make architectural decisions and the responsibility to deliver outcomes that drive real business impact.", - }, -]; - -export default function CareersPage() { - return ( -
- {/* ============================================ - HERO SECTION - ============================================ */} - - {/* TSOW Certification Badge */} -
- TSOW Certified Best Workplace -
-

- Officially a TSOW Certified Best Workplace -

-

- Recognized for creating a culture where people thrive. -

-
-
-
- - {/* ============================================ - WHY JOIN US SECTION - ============================================ */} -
- {/* Dot pattern */} -
- -
- -

- Why Join Procedure -

-

- Benefits Designed for Senior AI Engineers -

-

- Competitive compensation, flexible remote work, and continuous - learning opportunities. Everything you need to do career-defining - work on enterprise AI projects. -

-
- - {/* Benefits Grid */} -
- {benefits.map((benefit, idx) => ( - - {/* Card glow effect */} -
- -
-
- {benefit.icon} -
-

- {benefit.title} -

-

- {benefit.description} -

-
- - ))} -
-
-
- - {/* ============================================ - OUR VALUES SECTION - ============================================ */} -
- {/* Plus/cross pattern */} -
- -
- -

- Our Engineering Culture -

-

- The Values That Drive Our Work -

-

- A certified best workplace culture built on trust, technical excellence, - and a shared commitment to delivering production AI systems that - transform enterprises. -

-
- - {/* Values Grid */} -
- {values.map((value, idx) => ( - - {/* Card glow effect */} -
- -
-
-
- {idx + 1} -
-
-

- {value.title} -

-

- {value.description} -

-
-
-
- - ))} -
-
-
- - {/* ============================================ - HIRING PROCESS SECTION - ============================================ */} -
- {/* Dot pattern */} -
- -
- -

- How We Hire -

-

- Our Hiring Process -

-

- A transparent and efficient process designed to identify - exceptional talent. From application to offer, we move quickly - while ensuring the right fit for both sides. -

-
- - {/* Timeline - Desktop (Horizontal) */} -
-
- {/* Connecting line */} -
- -
- {[ - { - step: 1, - title: "Application Received", - description: - "Submit your application through our careers portal. We review all applications within 3-5 business days.", - icon: ( - - - - ), - }, - { - step: 2, - title: "TA Screening", - description: - "Quick call with our Talent Acquisition team to discuss your experience, career goals, and role expectations.", - icon: ( - - - - ), - }, - { - step: 3, - title: "HM Screening", - description: - "Technical conversation with the Hiring Manager to explore your skills, project experience, and approach.", - icon: ( - - - - ), - }, - { - step: 4, - title: "Interviews", - description: - "Technical assessments and team conversations covering coding exercises, system design, and cultural fit.", - icon: ( - - - - ), - }, - { - step: 5, - title: "Offer Release", - description: - "Receive your offer with a detailed compensation breakdown. We move fast and keep the process transparent.", - icon: ( - - - - ), - }, - ].map((item, idx) => ( - - {/* Step number circle */} -
-
- {/* Glow effect */} -
-
-
{item.icon}
-
-
-
- - {/* Card */} -
-
-
-
- STEP {item.step} -
-

- {item.title} -

-

- {item.description} -

-
-
- - ))} -
-
-
- - {/* Timeline - Mobile (Vertical) */} -
- {[ - { - step: 1, - title: "Application Received", - description: - "Submit your application through our careers portal. We review all applications within 3-5 business days.", - icon: ( - - - - ), - }, - { - step: 2, - title: "TA Screening", - description: - "Quick call with our Talent Acquisition team to discuss your experience, career goals, and role expectations.", - icon: ( - - - - ), - }, - { - step: 3, - title: "HM Screening", - description: - "Technical conversation with the Hiring Manager to explore your skills, project experience, and approach.", - icon: ( - - - - ), - }, - { - step: 4, - title: "Interviews", - description: - "Technical assessments and team conversations covering coding exercises, system design, and cultural fit.", - icon: ( - - - - ), - }, - { - step: 5, - title: "Offer Release", - description: - "Receive your offer with a detailed compensation breakdown. We move fast and keep the process transparent.", - icon: ( - - - - ), - }, - ].map((item, idx) => ( - - {/* Timeline line */} - {idx < 4 && ( -
- )} - - {/* Step number circle */} -
-
-
-
{item.icon}
-
-
- - {/* Card */} -
-
-
-
- STEP {item.step} -
-

- {item.title} -

-

- {item.description} -

-
-
- - ))} -
- - {/* Additional info */} - -

- - Total timeline: 2-3 weeks. - {" "} - We value your time and move quickly through each stage. You will - have a dedicated point of contact throughout the process to answer - questions and provide updates. -

-
-
-
- - {/* ============================================ - JOB OPENINGS SECTION - KEKA EMBED - ============================================ */} -
- {/* Hexagon pattern */} -
- -
- -

- Current Openings -

-

- Remote AI and Engineering Positions -

-

- All roles are fully remote with global hiring. We support - engineers across every timezone and prioritize asynchronous - collaboration. -

-
- - {/* Keka Careers Embed */} - - - -
-
- - {/* ============================================ - CTA SECTION - ============================================ */} -
- {/* Background gradient */} -
- - {/* Accent orbs */} -
-
- -
- -

- No Perfect Match? Let's Talk Anyway. -

-

- Exceptional AI talent is rare, and we are always building our - pipeline. Submit your resume with a note about your ideal role, - and we will reach out when the right opportunity emerges. -

- -
- - Submit Your Application - - - - - - Learn About Procedure - -
-
-
-
-
- ); + return ; } diff --git a/app/globals.css b/app/globals.css index fee1213..2a48fe3 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1587,65 +1587,89 @@ iframe { } /* ============================================================================= - KEKA CAREERS EMBED STYLING - Override Keka's default styles for better contrast on dark theme + JOB DESCRIPTION PROSE STYLING + Dark-theme styles for sanitized HTML content from Keka job descriptions ============================================================================= */ -#khembedjobs { - /* Give the embed a light background for readability */ - background-color: #ffffff; - border-radius: 1rem; - padding: 1.5rem; - color: #1a1a1a; +.prose-job-description { + font-family: var(--font-inter), system-ui, -apple-system, sans-serif; + color: rgba(255, 255, 255, 0.65); + line-height: 1.75; + font-size: 0.9375rem; } -/* Ensure all text inside Keka embed is readable */ -#khembedjobs * { - color-scheme: light; +.prose-job-description h1, +.prose-job-description h2, +.prose-job-description h3, +.prose-job-description h4, +.prose-job-description h5, +.prose-job-description h6 { + font-family: var(--font-outfit), system-ui, -apple-system, sans-serif; + color: rgba(255, 255, 255, 0.9); + font-weight: 600; + margin-top: 1.5rem; + margin-bottom: 0.75rem; } -/* Style the job cards */ -#khembedjobs a, -#khembedjobs .job-title, -#khembedjobs h3, -#khembedjobs h4 { - color: #1a1a1a !important; +.prose-job-description h3 { font-size: 1.125rem; } +.prose-job-description h4 { font-size: 1rem; } + +.prose-job-description p { + margin-bottom: 0.75rem; } -/* Style secondary text */ -#khembedjobs p, -#khembedjobs span, -#khembedjobs .job-location, -#khembedjobs .job-type { - color: #4a4a4a !important; +.prose-job-description ul { + list-style-type: disc; + padding-left: 1.25rem; + margin-bottom: 0.75rem; } -/* Style inputs and filters */ -#khembedjobs input, -#khembedjobs select { - background-color: #f5f5f5 !important; - border-color: #e0e0e0 !important; - color: #1a1a1a !important; +.prose-job-description ol { + list-style-type: decimal; + padding-left: 1.25rem; + margin-bottom: 0.75rem; } -#khembedjobs input::placeholder { - color: #888 !important; +.prose-job-description li { + margin-bottom: 0.375rem; + color: rgba(255, 255, 255, 0.65); } -/* Style buttons within Keka */ -#khembedjobs button { - color: #1a1a1a !important; +.prose-job-description li::marker { + color: var(--color-accent-light); } -/* Job card hover states */ -#khembedjobs [class*="job"], -#khembedjobs [class*="card"] { - background-color: #fafafa !important; - border-color: #e5e5e5 !important; +.prose-job-description strong, +.prose-job-description b { + color: rgba(255, 255, 255, 0.9); + font-weight: 600; } -#khembedjobs [class*="job"]:hover, -#khembedjobs [class*="card"]:hover { - background-color: #f0f0f0 !important; - border-color: var(--color-accent) !important; +.prose-job-description a { + color: var(--color-accent-light); + text-decoration: underline; + text-underline-offset: 2px; +} + +.prose-job-description a:hover { + color: var(--color-accent); +} + +.prose-job-description table { + width: 100%; + border-collapse: collapse; + margin-bottom: 1rem; +} + +.prose-job-description th, +.prose-job-description td { + padding: 0.5rem 0.75rem; + border: 1px solid var(--color-border); + text-align: left; +} + +.prose-job-description th { + color: rgba(255, 255, 255, 0.9); + font-weight: 600; + background-color: rgba(255, 255, 255, 0.05); } diff --git a/components/KekaJobsEmbed.tsx b/components/KekaJobsEmbed.tsx deleted file mode 100644 index 515134c..0000000 --- a/components/KekaJobsEmbed.tsx +++ /dev/null @@ -1,226 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import Script from "next/script"; - -interface KekaJobsEmbedProps { - className?: string; -} - -// Extend Window interface for Keka config -declare global { - interface Window { - khConfig?: { - identifier: string; - domain: string; - targetContainer: string; - }; - } -} - -export function KekaJobsEmbed({ className = "" }: KekaJobsEmbedProps) { - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - // Set up the Keka config - window.khConfig = { - identifier: "8f3224db-5bee-4b3f-825a-4138f9138f14", - domain: "https://procedure.keka.com/careers/", - targetContainer: "#khembedjobs", - }; - - // Set a timeout to hide loading state even if script doesn't trigger a callback - const timeout = setTimeout(() => { - setIsLoading(false); - }, 3000); - - return () => { - clearTimeout(timeout); - // Clean up config on unmount - delete window.khConfig; - }; - }, []); - - return ( -
- {/* Inject scoped styles for Keka embed - forces light theme */} -