From 2b0f5dc2fc81a5cea77e719d24909ef5af35f6c4 Mon Sep 17 00:00:00 2001 From: vibemarketerpromax Date: Mon, 16 Feb 2026 17:37:05 +0530 Subject: [PATCH] Revert "feat: Replace Keka embed with native API-driven job listings (#81)" This reverts commit 2a649503dfcbb40e2c66f0652af833b2c2c4697e. --- .env.example | 4 - .github/workflows/ci.yml | 4 - .github/workflows/nextjs.yml | 4 - .github/workflows/rebuild-jobs.yml | 23 - app/careers/CareersClient.tsx | 639 ----------------------- app/careers/page.tsx | 792 ++++++++++++++++++++++++++++- app/globals.css | 110 ++-- components/KekaJobsEmbed.tsx | 226 ++++++++ components/careers/JobCard.tsx | 152 ------ components/careers/JobFilters.tsx | 44 -- components/careers/JobListings.tsx | 160 ------ components/careers/index.ts | 3 - lib/keka-jobs.ts | 116 ----- lib/keka.ts | 147 ------ package-lock.json | 80 +-- package.json | 2 - 16 files changed, 1059 insertions(+), 1447 deletions(-) delete mode 100644 .github/workflows/rebuild-jobs.yml delete mode 100644 app/careers/CareersClient.tsx create mode 100644 components/KekaJobsEmbed.tsx delete mode 100644 components/careers/JobCard.tsx delete mode 100644 components/careers/JobFilters.tsx delete mode 100644 components/careers/JobListings.tsx delete mode 100644 components/careers/index.ts delete mode 100644 lib/keka-jobs.ts delete mode 100644 lib/keka.ts diff --git a/.env.example b/.env.example index d9e8d38..751ad6b 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,2 @@ 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 0ba1c03..a7a7895 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,10 +34,6 @@ 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 943d7e5..ef0547f 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -71,10 +71,6 @@ 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 deleted file mode 100644 index 09d7b5b..0000000 --- a/.github/workflows/rebuild-jobs.yml +++ /dev/null @@ -1,23 +0,0 @@ -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 deleted file mode 100644 index 9f8e01f..0000000 --- a/app/careers/CareersClient.tsx +++ /dev/null @@ -1,639 +0,0 @@ -"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 0107d6d..474d167 100644 --- a/app/careers/page.tsx +++ b/app/careers/page.tsx @@ -1,14 +1,786 @@ -import { getJobListings, getJobDepartments } from "@/lib/keka-jobs"; -import { CareersClient } from "./CareersClient"; +"use client"; -export const dynamic = "force-static"; -export const revalidate = false; +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 default async function CareersPage() { - const [jobs, departments] = await Promise.all([ - getJobListings(), - getJobDepartments(), - ]); +// 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.", + }, +]; - return ; +// 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 + +
+
+
+
+
+ ); } diff --git a/app/globals.css b/app/globals.css index 2a48fe3..fee1213 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1587,89 +1587,65 @@ iframe { } /* ============================================================================= - JOB DESCRIPTION PROSE STYLING - Dark-theme styles for sanitized HTML content from Keka job descriptions + KEKA CAREERS EMBED STYLING + Override Keka's default styles for better contrast on dark theme ============================================================================= */ -.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; +#khembedjobs { + /* Give the embed a light background for readability */ + background-color: #ffffff; + border-radius: 1rem; + padding: 1.5rem; + color: #1a1a1a; } -.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; +/* Ensure all text inside Keka embed is readable */ +#khembedjobs * { + color-scheme: light; } -.prose-job-description h3 { font-size: 1.125rem; } -.prose-job-description h4 { font-size: 1rem; } - -.prose-job-description p { - margin-bottom: 0.75rem; +/* Style the job cards */ +#khembedjobs a, +#khembedjobs .job-title, +#khembedjobs h3, +#khembedjobs h4 { + color: #1a1a1a !important; } -.prose-job-description ul { - list-style-type: disc; - padding-left: 1.25rem; - margin-bottom: 0.75rem; +/* Style secondary text */ +#khembedjobs p, +#khembedjobs span, +#khembedjobs .job-location, +#khembedjobs .job-type { + color: #4a4a4a !important; } -.prose-job-description ol { - list-style-type: decimal; - 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 li { - margin-bottom: 0.375rem; - color: rgba(255, 255, 255, 0.65); +#khembedjobs input::placeholder { + color: #888 !important; } -.prose-job-description li::marker { - color: var(--color-accent-light); +/* Style buttons within Keka */ +#khembedjobs button { + color: #1a1a1a !important; } -.prose-job-description strong, -.prose-job-description b { - color: rgba(255, 255, 255, 0.9); - font-weight: 600; +/* Job card hover states */ +#khembedjobs [class*="job"], +#khembedjobs [class*="card"] { + background-color: #fafafa !important; + border-color: #e5e5e5 !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); +#khembedjobs [class*="job"]:hover, +#khembedjobs [class*="card"]:hover { + background-color: #f0f0f0 !important; + border-color: var(--color-accent) !important; } diff --git a/components/KekaJobsEmbed.tsx b/components/KekaJobsEmbed.tsx new file mode 100644 index 0000000..515134c --- /dev/null +++ b/components/KekaJobsEmbed.tsx @@ -0,0 +1,226 @@ +"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 */} +