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
pnpm add @inploi/plugin-job-search
<script defer src="https://sdk.inploi.com/@inploi/sdk/cdn/index.js"></script>
<script defer src="https://sdk.inploi.com/@inploi/plugin-job-search/cdn/index.js"></script>
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),
});
<script defer src="https://sdk.inploi.com/@inploi/sdk/cdn/index.js"></script>
<script defer src="https://sdk.inploi.com/@inploi/plugin-job-search/cdn/index.js"></script>
<div data-widget="inploi-job-search" data-widget-id="main"></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const sdk = inploi.initialiseSdk({ publishableKey: 'pk_...', env: 'sandbox' });
const jobSearch = sdk.register(inploi.jobSearchPlugin());
jobSearch.render({
widgetId: 'main',
properties: [{ key: 'city', label: 'City', select: 'many' }],
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: function(state) { console.log('State changed', state); },
});
});
</script>
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
| Option | Type | Description |
|---|
mode | light, dark | Color scheme |
corners | sharp, soft, rounded | Border radius style |
highlights | fill, stroke | Button/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 |
typography | object | Font 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' },
]
| Option | Type | Description |
|---|
key | string | Job field key or custom_data.* path |
label | string | Display label |
select | one, many | Single or multi-select |
icon | string | Override the default filter icon |
searchable | boolean | Allow searching within filter options |
hidden | boolean | Hide from UI (useful for hard-coded filters) |
value | string | string[] | Fixed filter value (cannot be changed by user) |
defaultValue | string | string[] | Default value (can be changed by user) |
results | all, only-available | Whether 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',
}
| Option | Type | Description |
|---|
subheading | { key, transform? } | null | Field to show as subheading |
infoTags | { key, transform? }[] | Fields to show as tags on the card |
logo | hidden, 1:1, 2:1 | Company logo display |
postedDate | show, hide, only-new | Posted date display |
newUnderDays | number | Days for a job to be considered new (default 7) |
openJob | redirect, redirect-new-tab | How to open job links |
overrides | object | Override salary display, job URL, or click/hover behavior |
Other options
| Option | Type | Required | Description |
|---|
initialState | object | function | Yes | Initial state: { filters: {}, query: '', mode: 'query', page: 1, view: 'list' }. Can also be a function receiving config and returning state |
widgetId | string | No | Identifies the widget when using multiple instances |
enableKeywordSearch | boolean | No | Enable keyword search input |
geolocation | { enabled: boolean, distanceUnit?: string } | No | Enable location-based search. distanceUnit: miles or km |
naturalLanguageSearch | { enabled: boolean, suggestions: string[] } | No | Enable AI-powered natural language search with suggested queries |
i18n | { locale?: string, fallbackLocale?: string } | No | Locale settings (e.g. 'en', 'fr') |
terms | object | No | Override default UI text (~65 keys covering search labels, filters, errors, dates, geo-search, map, and job types) |
map | object | No | Enable map view: { enabled: boolean, accessToken?: string, style?: string, pinColor?: string, defaultCenter?: [lng, lat] } |
feedback | object | No | Embed feedback widget (see Feedback plugin) |
alerts | object | No | Embed 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 });