npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hiofu/apply-sdk

v0.1.7

Published

Browser SDK for HIOFU Apply with OAuth, HSP1 review, and idempotent application submission.

Readme

@hiofu/apply-sdk

Browser SDK for HIOFU Apply.

Use it to add a HIOFU-powered application flow to job boards, ATS products, and employer career sites. The SDK handles:

  • OAuth 2.0 Authorization Code with PKCE
  • HSP1 review and candidate consent in a popup
  • role routing from your job/page IDs to HIOFU roles
  • immutable application snapshot creation
  • idempotent application submission
  • structured success, cancellation, and error handling

Install

npm install @hiofu/apply-sdk

Quick Start

React Button

import { HiofuApplyButton } from "@hiofu/apply-sdk/react";

export function ApplyButton({ jobId, jobTitle }) {
  return (
    <HiofuApplyButton
      clientId={process.env.NEXT_PUBLIC_HIOFU_KEY}
      variant="primary"
      options={{
        jobId,
        jobTitle,
      }}
    />
  );
}

The React button uses the lower-level HiofuClient API, where the publishable key is passed as clientId.

TypeScript Client

import { createApplyClient } from "@hiofu/apply-sdk";

const hiofu = createApplyClient({
  publicKey: "pk_test_xxx",
});

const result = await hiofu.apply({
  jobId: "job_123",
  externalEmployerId: "emp_456",
  employerName: "Acme Inc",
  role: {
    title: "Senior Engineer",
    description: "Build and operate HIOFU integrations.",
    locations: ["London", "Remote"],
    skills: ["TypeScript", "API integrations"],
  },
  idempotencyKey: "apply_attempt_01JXYZ",
});

console.log(result.applicationId);
console.log(result.raw.application.status);

createApplyClient is the recommended imperative browser API for new non-React integrations. It resolves HIOFU URLs from the key prefix and returns a normalized result while keeping the full API response under result.raw.

Environments

Switch environments by changing the publishable key.

| Mode | Publishable key | HIOFU origin | API base | | --- | --- | --- | --- | | Sandbox | pk_test_* | https://sandbox.hiofu.com | https://api.sandbox.hiofu.com/api | | Production | pk_live_* | https://hiofu.com | https://api.hiofu.com/api |

const hiofu = createApplyClient({
  publicKey:
    process.env.NODE_ENV === "production" ? "pk_live_xxx" : "pk_test_xxx",
});

pk_test_* keys can only talk to sandbox endpoints. pk_live_* keys can only talk to production endpoints.

createApplyClient

import { createApplyClient } from "@hiofu/apply-sdk";

const hiofu = createApplyClient({
  publicKey: "pk_test_xxx",
  storage: "memory",
  popupOptions: {
    timeoutMs: 300_000,
  },
  onComplete(result) {
    console.log("Application submitted", result.applicationId);
  },
  onCancel(context) {
    console.log("Apply cancelled", context.reason);
  },
  onError(error) {
    console.warn(error.code, error.correlationId, error.retryable);
  },
});

Configuration:

  • publicKey (required): publishable key, for example pk_test_xxx or pk_live_xxx.
  • environment: inferred from the key prefix. Override with "sandbox" or "production" only when you need explicit validation.
  • redirectUri: defaults to the HIOFU-hosted callback. Set this only when you host your own callback page.
  • scopes: default scopes for authorize().
  • applyScopes: default scopes for apply().
  • storage: "memory" by default, or "session" to persist the access token for the browser session.
  • popupOptions.timeoutMs: popup wait limit in milliseconds. Defaults to 300_000.
  • onComplete(result): receives a normalized apply result.
  • onCancel(context): receives user-cancel, popup-close, and timeout events.
  • onError(error): receives a typed HiofuApplyError.
  • onEvent(event): receives lower-level lifecycle events.

hiofuOrigin and apiBase are also available for local/internal testing. Most partner integrations should rely on publicKey and environment instead.

Apply Payload

createApplyClient.apply() accepts partner-owned job and role data:

await hiofu.apply({
  jobId: "job_123",
  externalEmployerId: "emp_456",
  employerName: "Acme Inc",
  jobTitle: "Senior Engineer",
  role: {
    title: "Senior Engineer",
    description: "Role description from your system.",
    location: "London",
    locations: ["London", "Remote"],
    salary: "GBP 90k-110k",
    skills: ["TypeScript", "Node.js"],
    dimensions: {
      backend: 5,
      productJudgement: 4,
    },
    metadata: {
      source: "ats",
    },
  },
  partnerTags: {
    campaign: "summer-hiring",
  },
  callbackState: "opaque_state_from_your_app",
  idempotencyKey: "apply_attempt_01JXYZ",
});

Rules:

  • Provide either jobId or externalJobId.
  • role.title is required and becomes jobTitle when jobTitle is omitted.
  • externalEmployerId is optional for single-employer integrations, but recommended for multi-employer job boards.
  • idempotencyKey is required for createApplyClient.apply(). Use a stable partner-generated application attempt ID.
  • variationId is optional. When omitted, the popup asks the candidate which HSP1 view to share.

Normalized Result

type HiofuNormalizedApplyResult = {
  applicationId: string;
  partnerApplicationId?: string;
  hiofuRoleId: string;
  status: string;
  environment: "sandbox" | "production";
  submittedAt: string;
  raw: HiofuApplyResult;
};

Use raw when you need snapshot, profile, evidence, delivery, or authorization details returned by the HIOFU API.

React

React exports live at @hiofu/apply-sdk/react.

Standalone Button

import { HiofuApplyButton } from "@hiofu/apply-sdk/react";

<HiofuApplyButton
  clientId="pk_test_xxx"
  variant="primary"
  options={{
    jobId: "job_123",
    jobTitle: "Senior Engineer",
    employerId: "emp_456",
    employerName: "Acme Inc",
  }}
  onSuccess={(result) => {
    console.log(result.application.id);
  }}
  onError={(error) => {
    console.error(error.message);
  }}
/>

HiofuApplyButton variants are primary, secondary, and ghost. The button creates its own HiofuClient when clientId is provided.

Provider

Use a provider when multiple buttons or hooks share the same client config.

import { HiofuApplyButton, HiofuProvider } from "@hiofu/apply-sdk/react";

<HiofuProvider
  config={{
    clientId: "pk_test_xxx",
    storage: "memory",
  }}
>
  <HiofuApplyButton
    options={{ jobId: "job_1", jobTitle: "Role A" }}
  />
  <HiofuApplyButton
    options={{ jobId: "job_2", jobTitle: "Role B" }}
  />
</HiofuProvider>;

Custom Button

import { HiofuProvider, useHiofuApply } from "@hiofu/apply-sdk/react";

function CustomApplyButton() {
  const { apply, status, error, result, reset } = useHiofuApply();
  const busy = status === "authorising" || status === "submitting";

  return (
    <div>
      <button
        disabled={busy}
        onClick={async () => {
          try {
            await apply({
              jobId: "job_123",
              jobTitle: "Senior Engineer",
              employerId: "emp_456",
              employerName: "Acme Inc",
            });
          } catch {
            // State is exposed through `error`.
          }
        }}
      >
        {status === "success" ? "Submitted" : "Apply with HIOFU"}
      </button>

      {status === "error" && <p role="alert">{error?.message}</p>}
      {status === "success" && (
        <p>Application ID: {result?.application.id}</p>
      )}
      {(status === "error" || status === "success") && (
        <button onClick={reset}>Try again</button>
      )}
    </div>
  );
}

export function Page() {
  return (
    <HiofuProvider config={{ clientId: "pk_test_xxx" }}>
      <CustomApplyButton />
    </HiofuProvider>
  );
}

useHiofuApply() must be used inside HiofuProvider.

Lower-Level HiofuClient

HiofuClient remains available for compatibility and for integrations that need direct access to authorization/profile helpers.

import { HiofuClient } from "@hiofu/apply-sdk";

const hiofu = new HiofuClient({
  clientId: "pk_test_xxx",
  storage: "session",
  authorizeTimeoutMs: 300_000,
});

const result = await hiofu.apply({
  jobId: "job_123",
  jobTitle: "Senior Engineer",
  employerId: "emp_456",
  employerName: "Acme Inc",
});

console.log(result.application.id);

With HiofuClient.apply(), idempotencyKey is optional. If omitted, the SDK generates one for the attempt and sends it in both the request header and body.

Hosted Script

Use the hosted/global build for static pages or no-build job boards.

<script
  src="https://cdn.hiofu.com/apply-sdk.global.js"
  data-client-id="pk_test_xxx"
></script>

<button
  data-hiofu-apply
  data-job-id="job_123"
  data-job-title="Senior Engineer"
  data-employer-id="emp_456"
  data-employer-name="Acme Inc"
  data-external-role-id="job_123"
  data-external-employer-id="emp_456"
  data-role-title="Senior Engineer"
  data-role-department="Engineering"
  data-role-locations="London,Remote"
>
  Apply with HIOFU
</button>

Required button attributes:

  • data-job-id
  • data-job-title

Optional button attributes include:

  • data-employer-id
  • data-employer-name
  • data-hiofu-scopes
  • data-hiofu-variation-id
  • data-hiofu-idempotency-key
  • data-external-role-id
  • data-external-employer-id
  • data-role-title
  • data-role-description
  • data-role-department
  • data-role-locations
  • data-role-job-types
  • data-role-salary-min
  • data-role-salary-max
  • data-role-salary-currency
  • data-role-experience-min
  • data-role-experience-max

Listen for DOM events to update your UI:

<script>
  document.addEventListener("hiofu:apply:success", (event) => {
    console.log(event.detail.application.id);
  });

  document.addEventListener("hiofu:apply:error", (event) => {
    console.error(event.detail);
  });
</script>

Script attributes:

  • data-client-id: required publishable key.
  • data-hiofu-origin: optional local/internal origin override.
  • data-api-base: optional local/internal API override.
  • data-redirect-uri: optional partner-hosted callback URI.
  • data-scopes: optional authorization scopes.
  • data-apply-scopes: optional apply scopes.

Role Routing

Keep sending the same job or page ID your system already uses. Before going live, save a mapping from that ID to the destination HIOFU role in Developer settings or with the management client:

your job/page ID -> HIOFU role

For single-employer integrations, HIOFU can derive the workspace from the publishable key. For multi-employer sites, pass externalEmployerId with createApplyClient or employerId/role.externalEmployerId with HiofuClient.

The browser SDK should send your own job/page ID, not an internal HIOFU role ID. If no active mapping exists for the current environment, the API rejects the submission and no application is created.

Management Client

The management client automates setup actions from trusted backend code or internal tooling. Do not expose its access token to browsers.

import { createManagementClient } from "@hiofu/apply-sdk";

const management = createManagementClient({
  apiBase: "https://api.sandbox.hiofu.com/api",
  accessToken: process.env.HIOFU_EMPLOYER_ACCESS_TOKEN,
});

Create or update a destination role:

const role = await management.createRole({
  title: "Senior Engineer",
  department: "Engineering",
  description: "Role description from your system.",
  locations: ["London", "Remote"],
});

await management.updateRoleStatus(role.id, "hiring");

Issue a publishable key and map your external role ID:

await management.issuePublishableKey();

await management.saveRoleMapping({
  mode: "test",
  externalRoleId: "job_123",
  externalEmployerId: "emp_456",
  employerRoleId: role.id,
});

Register a callback URI only when you override the HIOFU-hosted callback:

await management.addRedirectUri({
  mode: "test",
  uri: "https://jobs.example.com/oauth/callback.html",
});

Other available management methods:

  • listRoles(params)
  • getRole(roleId)
  • updateRole(roleId, input)
  • updateRoleStatus(roleId, status)
  • getDeveloperSettings()
  • removeRedirectUri(uriId)

Custom Callback Handling

Most integrations do not need a callback page. When redirectUri is omitted, the SDK uses the HIOFU-hosted callback for the key's environment.

Only host your own callback when you have a specific same-origin requirement. In that case, register the exact callback URL in HIOFU Developer settings and pass it as redirectUri.

<!doctype html>
<html lang="en">
  <meta charset="UTF-8" />
  <title>Returning</title>
  <body>
    Returning to the application
    <script>
      (() => {
        const p = new URLSearchParams(window.location.search);
        const payload = {
          type: "hiofu_oauth",
          code: p.get("code"),
          state: p.get("state"),
          error: p.get("error"),
          variationId: p.get("variation_id"),
        };

        if (window.opener) {
          try {
            window.opener.postMessage(payload, window.location.origin);
          } catch {}
        }

        try {
          if (typeof BroadcastChannel !== "undefined") {
            const ch = new BroadcastChannel("hiofu_oauth");
            ch.postMessage(payload);
            ch.close();
          }
        } catch {}

        try {
          localStorage.setItem("hiofu_oauth_result", JSON.stringify(payload));
        } catch {}

        setTimeout(() => {
          try {
            window.close();
          } catch {}
        }, 150);
      })();
    </script>
  </body>
</html>

Scopes

  • profile.basic: minimal profile summary for your apply UX.
  • profile.full: sanitized HSP1 profile summary including skills and redacted work/education history.
  • evidence.read: evidence titles, types, and aggregate trust signals.
  • applications.write: submit an application on the candidate's behalf.
  • passport.snapshot: create and return an immutable hiring snapshot with summary previews.

apply() requests the minimal browser-safe bundle by default:

  • applications.write
  • passport.snapshot

The SDK automatically includes those two scopes for application submissions.

Events

Subscribe with onEvent or HiofuClient.subscribe():

  • popup_opened
  • popup_result_received
  • popup_closed
  • token_issued
  • apply_started
  • apply_submitting
  • apply_success
  • apply_error

Errors

createApplyClient wraps runtime failures in HiofuApplyError:

import { HiofuApplyError, createApplyClient } from "@hiofu/apply-sdk";

const hiofu = createApplyClient({
  publicKey: "pk_test_xxx",
});

try {
  await hiofu.apply({
    jobId: "job_123",
    role: { title: "Senior Engineer" },
    idempotencyKey: "apply_attempt_01JXYZ",
  });
} catch (error) {
  if (error instanceof HiofuApplyError) {
    console.warn(error.code, error.correlationId, error.retryable);
  }
}

Error codes:

  • configuration_error
  • environment_mismatch
  • popup_blocked
  • popup_closed
  • auth_failed
  • consent_required
  • role_mapping_failed
  • submit_failed
  • timeout

Lower-level exports:

  • HiofuConfigurationError: invalid SDK configuration.
  • HiofuApiError: HTTP errors from the HIOFU API, including status and parsed body when available.
  • HiofuPopupError: popup closed or timed out before authorization completed.

Security Notes

  • Prefer the HIOFU-hosted callback.
  • Register only callback domains you control.
  • Browser integrations receive a short-lived access token through the SDK runtime. Refresh tokens are not exposed to your UI code.
  • The SDK defaults to in-memory token storage.
  • Session storage persists access tokens only and strips refresh tokens.
  • Do not log raw application payloads in production UIs.
  • Use a stable idempotency key when your system already has an application attempt ID.
  • The popup times out after 5 minutes by default. Use popupOptions.timeoutMs with createApplyClient or authorizeTimeoutMs with HiofuClient.

Brand Helpers

The package exports HIOFU brand constants and an inline SVG mark:

import {
  HIOFU_BRAND_COLOR,
  HIOFU_BUTTON_LABEL,
  HIOFU_WORDMARK,
  HIOFU_TAGLINE,
  hiofuLogoSvg,
} from "@hiofu/apply-sdk";

The SDK does not inject third-party fonts or global styles into your app. Your app should own its font-loading strategy.

Examples

Working examples live in the repository's examples/ directory:

  • static HTML
  • Next.js job board
  • vanilla TypeScript SPA
  • Express webhook receiver