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

@khirby/forms-client

v0.3.0

Published

Khirby forms client — submit landing page forms with typed fields from CRM schema

Readme

@khirby/forms-client

Low-level SDK for Khirby public forms. Docs: forms-client · Landing forms

CRM is the source of truth for field schema. This package only talks to:

| Method | Path | |--------|------| | GET | /api/public/forms/:token | | POST | /api/public/forms/:token/submit | | POST | /api/public/forms/:token/adaptive/plan | | POST | /api/public/forms/:token/inquiries |

:token = form endpoint token from CRM → Forms → Integration (not a session JWT).

When to use this vs forms-ui

| Package | Use when | |---------|----------| | forms-client | Headless submit, Node scripts, codegen, custom UI | | forms-ui | Ready React form that fetches fields + renders + submits | | payload-forms | Payload admin: registry of tokens + page block |

Most landings should use forms-ui (which depends on this package).

Install

echo @khirby:registry=https://registry.npmjs.org >> .npmrc
npm i @khirby/forms-client

Full public guide: landing-site product docs (forms). In-repo author notes: this package README.

Monorepo / workspace:

pnpm --filter @khirby/forms-client build
pnpm add @khirby/forms-client@workspace:*

Quick start

import { createClient, CrmFormsError } from '@khirby/forms-client'

const crm = createClient({
  baseUrl: 'https://crm.example.com', // no trailing slash
})

// 1) Load schema (labels, types, required)
const form = await crm.getForm('<endpointToken>')
// form.fields: { name, label, type, required, options? }[]

// 2) Submit — flat object, field names = schema `name`s
//    `email` is always required by CRM
await crm.submit('<endpointToken>', {
  email: '[email protected]',
  name: 'Jan',
  message: 'Hello',
})

Payload shape rules

  • Flat JSON — not { data: { … } }
  • Top-level email always required
  • Unknown keys rejected when CRM schema is non-empty
  • Client adds honeypot _hp: '' on submit
  • Field types: text | email | tel | url | number | textarea | checkbox | select

Bound form helper

const form = await crm.form('<endpointToken>')
form.fields
await form.submit({ email: '…', name: '…' })

Errors

try {
  await crm.submit(token, data)
} catch (e) {
  if (e instanceof CrmFormsError) {
    // e.status, e.message, e.body
  }
}

Codegen (optional)

pnpm exec khirby-forms-codegen \
  --base-url https://crm.example.com \
  --form <endpointToken> \
  --out ./src/generated/contact-form.ts

CORS

Browser posts need the landing origin in CRM CORS_ORIGIN. Server-side posts do not.

Build / test

pnpm --filter @khirby/forms-client build
pnpm --filter @khirby/forms-client test

Package is ESM ("type": "module") so Vite/Next can import named exports.