Join The Studio

Careers At Polaris

Make work you would be proud to sign.

We are a small studio with a long memory. The people we hire stay because the work is honest, the feedback is generous, and the craft is never an afterthought. If you care about the details nobody asked you to fix, you will feel at home here.

  • Four-day weeks, all summer long.
  • A real budget for tools, courses, and conferences.
  • Profit sharing from your first project.
  • Remote-first, with two studio weeks a year.
See all roles
About this block

Join The StudioPRO

Sticky employer-value intro beside a scrollable open-roles list.

Careers48: Join The Studio

A two-column careers section: a sticky left panel holds a badge, heading, description, a bulleted employer-value list, and a CTA button, while the right column renders a bordered, vertically stacked list of open roles as full-width anchor links, each showing a title, a department-and-location line, and an arrow icon that nudges on hover.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/careers48?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/careers48?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/careers48.tsx.

Quick start

The installed file exports careers48Demo alongside the block: the exact props behind the preview above. Spread it to get a working careers section in one line.

tsx
import { Careers48, careers48Demo } from "@/components/beste/block/careers48";

export default function CareersPage() {
  return <Careers48 {...careers48Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Careers48 } from "@/components/beste/block/careers48";

export default function CareersPage() {
  return (
    <Careers48
      label="Careers At Polaris"
      heading="Make work you would be proud to sign."
      description="A small studio with a long memory, where craft is never an afterthought."
      evp={[
        "Four-day weeks, all summer long.",
        "Profit sharing from your first project.",
      ]}
      cta={{ label: "See all roles", href: "/careers" }}
      roles={[
        {
          title: "Senior Brand Designer",
          department: "Design",
          location: "Remote — Europe",
          href: "/careers/senior-brand-designer",
        },
        {
          title: "Motion Director",
          department: "Motion",
          location: "Remote — Global",
          href: "/careers/motion-director",
        },
      ]}
    />
  );
}

Props

PropTypeDefaultDescription
labelstringEyebrow text passed to the Badge6 component; hidden when absent
headingstringSection heading rendered as plain text in an <h2>
descriptionstringIntro paragraph below the heading
evpstring[][]Employer-value bullets, each with a decorative square marker
ctaCtaLinkLabel and href for the Button1 link at the bottom of the left panel
rolesRole[][]Open-role rows rendered as anchor links in the right column
classNamestringExtra classes merged onto the outer <section>
ts
type CtaLink = {
  label: string;
  href: string;
};

type Role = {
  title: string;
  department: string;
  location: string;
  href: string;
};

Behavior notes

  • The block is purely presentational: it holds no useState, fires no callbacks, and navigation happens entirely through native anchor href values, so there is nothing to wire up beyond passing URLs.
  • The left panel is sticky on lg screens via lg:sticky lg:top-24 and stays pinned while the roles column scrolls past with the page; there is no internal overflow container or max-h, so a long roles list simply extends the page height.
  • Every section of the left panel renders conditionally: label, heading, description, and cta each require a truthy value, and the evp list only appears when evp.length > 0.
  • The columns use a fixed lg:grid-cols-[0.85fr_1.15fr] ratio, giving the roles list slightly more width than the intro; below lg they stack into a single column.
  • heading is rendered as plain text with no dangerouslySetInnerHTML, so inline <strong> or other markup in the string will be shown literally, not parsed.
  • Each role row is keyed by array index and links to role.href; the title turns to text-primary and the trailing ArrowUpRight icon translates on group-hover/careers48.
  • The cta renders through Button1 with asChild wrapping a next/link Link and a fixed ArrowUpRight icon; the icon on both the CTA and role rows is hardcoded and not configurable via props.

More Careers blocks

View all Careers
PRO

careers40

Open Roles

A studio jobs list with role meta, salary and apply arrows.

PRO

careers57

Open Roles With Published Bands

A short roles list where the pay band sits on the row rather than behind an application, with a written empty state for when nothing is open and a speculative line underneath.

PRO

careers46

Role Spotlight

A full featured-role posting with responsibilities, requirements and a sticky apply card.

PRO

careers44

Roles By Department

Department-tabbed open roles list using shadcn Tabs.

PRO

careers1

Job Listings List

Job listings section with role cards showing department, location, and employment type. Clean list layout with hover effects and apply buttons.

PRO

careers58

Fourth Chair Roles

A careers section: a serif heading that settles in word by word, an intro, a pill action and a photograph drifting inside its frame on the left, beside ruled open roles with serif titles and small-caps type and place that lift an arrow on hover, and a note on how applications are answered.