Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.inploi.com/llms.txt

Use this file to discover all available pages before exploring further.

Job Search Plugin

The Job Search plugin renders a complete job search interface with filters, search, and job cards.

Installation

npm install @inploi/plugin-job-search

Basic usage

import { initialiseSdk } from '@inploi/sdk';
import { jobSearchPlugin } from '@inploi/plugin-job-search';

const sdk = initialiseSdk({ publishableKey: 'pk_...', env: 'sandbox' });
const jobSearch = sdk.register(jobSearchPlugin());

jobSearch.render({
  widgetId: 'main',
  properties: [
    { key: 'city', label: 'City', select: 'many' },
    { key: 'contract_type', label: 'Contract', select: 'one' },
  ],
  jobCard: {
    subheading: { key: 'company_name' },
    infoTags: [{ key: 'city' }],
  },
  theme: {
    mode: 'light',
    corners: 'soft',
    highlights: 'fill',
    accent: { hue: 260, chroma: 1 },
    typography: {},
  },
  initialState: { filters: {}, query: '', mode: 'query', page: 1, view: 'list' },
  onStateChange: (state) => console.log('State changed', state),
});

Host element

Add a container element where the widget will render:
<div data-widget="inploi-job-search" data-widget-id="main"></div>
Use data-widget-id to identify the container when rendering multiple widgets on the same page.

Configuration

Theme

OptionTypeDescription
modelight, darkColor scheme
cornerssharp, soft, roundedBorder radius style
highlightsfill, strokeButton/tag style
accent{ hue: number, chroma: number }Primary accent color. hue: 0–360 color angle, chroma: 0–2 intensity multiplier
neutral{ hue: number, chroma: number }Optional neutral base color (same format as accent)
monetary{ hue: number, chroma: number }Optional color for salary/monetary values
typographyobjectFont settings: { fontFamily: string, weight: number | string, style: string }. Supports per-slot overrides: filter, tag, input, jobHeading
accessibility{ highContrast: boolean, reducedMotion: boolean }Accessibility preferences

Properties (Filters)

Define which job properties appear as filters:
properties: [
  { key: 'city', label: 'City', select: 'many' },
  { key: 'contract_type', label: 'Contract', select: 'one', searchable: true },
  { key: 'custom_data.tags', label: 'Category', select: 'one' },
]
OptionTypeDescription
keystringJob field key or custom_data.* path
labelstringDisplay label
selectone, manySingle or multi-select
iconstringOverride the default filter icon
searchablebooleanAllow searching within filter options
hiddenbooleanHide from UI (useful for hard-coded filters)
valuestring | string[]Fixed filter value (cannot be changed by user)
defaultValuestring | string[]Default value (can be changed by user)
resultsall, only-availableWhether to show all options or only those with results
sortSuggestions{ by: string, order: string }by: results-count, alphabetically, or numerically. order: ascending or descending

Job Card

Customize how job cards display:
jobCard: {
  subheading: { key: 'company_name' },
  infoTags: [
    { key: 'city' },
    { key: 'employment_type' },
    { key: 'contract_type' },
  ],
  logo: '2:1',
  postedDate: 'show',
  openJob: 'redirect',
}
OptionTypeDescription
subheading{ key, transform? } | nullField to show as subheading
infoTags{ key, transform? }[]Fields to show as tags on the card
logohidden, 1:1, 2:1Company logo display
postedDateshow, hide, only-newPosted date display
newUnderDaysnumberDays for a job to be considered new (default 7)
openJobredirect, redirect-new-tabHow to open job links
overridesobjectOverride salary display, job URL, or click/hover behavior

Other options

OptionTypeRequiredDescription
initialStateobject | functionYesInitial state: { filters: {}, query: '', mode: 'query', page: 1, view: 'list' }. Can also be a function receiving config and returning state
widgetIdstringNoIdentifies the widget when using multiple instances
enableKeywordSearchbooleanNoEnable keyword search input
geolocation{ enabled: boolean, distanceUnit?: string }NoEnable location-based search. distanceUnit: miles or km
naturalLanguageSearch{ enabled: boolean, suggestions: string[] }NoEnable AI-powered natural language search with suggested queries
i18n{ locale?: string, fallbackLocale?: string }NoLocale settings (e.g. 'en', 'fr')
termsobjectNoOverride default UI text (~65 keys covering search labels, filters, errors, dates, geo-search, map, and job types)
mapobjectNoEnable map view: { enabled: boolean, accessToken?: string, style?: string, pinColor?: string, defaultCenter?: [lng, lat] }
feedbackobjectNoEmbed feedback widget (see Feedback plugin)
alertsobjectNoEmbed job alerts (see Job Alerts plugin)

Full configuration reference

type JobSearchPluginParams = {
  widgetId?: string;
  theme: {
    mode: 'light' | 'dark';
    corners: 'rounded' | 'soft' | 'sharp';
    highlights: 'stroke' | 'fill';
    accent: { hue: number; chroma: number };
    neutral?: { hue: number; chroma: number };
    monetary?: { hue: number; chroma: number };
    typography: Partial<FontSettings> & Partial<Record<TextStyle, Partial<FontSettings>>>;
    filtersOffsetTopPx?: number;
    accessibility?: { highContrast: boolean; reducedMotion: boolean };
  };
  properties: FilterProperty[];
  jobCard: {
    subheading: { key: string; transform?: (v: unknown) => string | string[] | null } | null;
    infoTags: { key: string; transform?: (v: unknown) => string | string[] | null }[];
    logo?: 'hidden' | '1:1' | '2:1';
    postedDate?: 'hide' | 'show' | 'only-new';
    newUnderDays?: number;
    openJob?: 'redirect' | 'redirect-new-tab';
    overrides?: {
      salary?: { key: string; transform?: Function };
      baseUrl?: (jobId: string) => string;
      onClick?: (e: MouseEvent) => void;
      onMouseEnter?: (e: MouseEvent) => void;
    };
  };
  initialState: JobSearchState | ((params: Omit<JobSearchPluginParams, 'initialState'>) => JobSearchState);
  enableKeywordSearch?: boolean;
  geolocation?: { enabled: boolean; distanceUnit?: 'miles' | 'km' };
  naturalLanguageSearch?: { enabled: boolean; suggestions: string[] };
  terms?: Partial<JobSearchTranslationTerms>;
  i18n?: { locale?: string; fallbackLocale?: string };
  alerts?: {
    plugin: ReturnType<typeof jobAlertsPlugin>;
    params: { config: { label: string; headerText: string } };
  };
  feedback?: {
    plugin: FeedbackPlugin;
    params?: { terms?: Partial<FeedbackTranslationTerms>; theme: Partial<FeedbackTheme> };
  };
  map?: {
    enabled: boolean;
    accessToken?: string;
    style?: string;
    pinColor?: string;
    defaultCenter?: [number, number];
  };
};

type FontSettings = {
  fontFamily: string;
  weight: 'normal' | 'bold' | 'lighter' | 'bolder' | number;
  style: 'normal' | 'italic';
};

type TextStyle = 'filter' | 'tag' | 'input' | 'jobHeading';

type FilterProperty = {
  key: string;
  label: string;
  select: 'one' | 'many';
  icon?: string;
  searchable?: boolean;
  hidden?: boolean;
  value?: string | string[];
  defaultValue?: string | string[];
  results?: 'all' | 'only-available';
  sortSuggestions?: {
    by: 'results-count' | 'alphabetically' | 'numerically';
    order: 'ascending' | 'descending';
  };
};

type JobSearchState = {
  filters: Record<string, FilterValue | undefined>;
  query: string;
  mode: 'query' | 'vector';
  geo?: GeoSearchFilter;
  page: number;
  view: 'list' | 'map';
};

API

render(params)

Mounts the job search UI in the host element. Requires an onStateChange callback in addition to the configuration above. The callback receives a partial state object whenever a slice of the widget state changes (filters, query, page, view, etc.).
jobSearch.render({
  // ...configuration
  onStateChange: (partial) => console.log(partial),
});
Pass initialData when hydrating a server-rendered widget (see prerender below).

prerender(params)

Returns HTML for server-side rendering. Use withData: true to fetch initial results on the server.
const { html, data } = await jobSearch.prerender({ ...config, withData: true });