Legacy Apps SDKlegacy

Reference for the deprecated TypeScript Apps SDK (KAppServer, the client and React SDKs, and the apps CLI), and how to migrate an SDK app to a JSON app definition.

The Apps SDK was a TypeScript framework for building Kustomer apps as a hosted service. You wrote an Express server with KAppServer, which generated the app definition from code, registered it, received events and webhooks, and served client-side KViews.

Packages

PackageWhat it did
@kustomer/apps-serverKAppServer, an Express app that registers the definition and routes hooks and events to handlers
@kustomer/apps-clientA framework-agnostic library for client-side KViews
@kustomer/apps-react-clientReact components for KViews in Kustomer's design system, built on apps-client
@kustomer/apps-commonShared types (such as SettingsManifest) and API helpers used by the client and server
@kustomer/apps-tokensDesign tokens for the React components
@kustomer/apps-cliScaffolds new apps (npx @kustomer/apps-cli new <name>) and registers them

How an SDK app looks

src/kapp.ts
import { KAppServer } from '@kustomer/apps-server'
import pkg from '../package.json'
import changelog from '../changelog.json'
import { settings } from './settings'
import * as klasses from './klasses'
import * as events from './events'

const kapp = new KAppServer({
  app: pkg.name,
  version: pkg.version,
  title: 'Acme Orders',
  visibility: 'private',
  description: 'Orders from Acme, on the customer timeline.',
  roles: [],
  url: process.env.BASE_URL,
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  iconUrl: `${process.env.BASE_URL}/assets/icon.png`,
  changelog,
  appDetails: {
    appDeveloper: { name: 'Acme', website: 'https://acme.example', supportEmail: 'support@acme.example' },
  },
  settings,
})

kapp.onInstall = async (user, org) => {
  kapp.log.info('onInstall', { user, org })
}

kapp.klasses.register(klasses.order.name, klasses.order.schema)
kapp.serverHooks.on('order', klasses.order.onHook)
kapp.events.on('customer', 'create', events.customer.create(kapp))

export default kapp
src/index.ts
import kapp from './kapp'

await kapp.start({ port: Number(process.env.PORT ?? 3000) })

The constructor options are the same top-level keys as a JSON definition, plus the URL your server is reachable at. settings uses the same shape as a definition's settings.

Migrate to an app definition

Most SDK apps translate directly. The work is moving logic that ran in your handlers into Kustomer workflows, actions and commands, so that Kustomer runs it instead of your server.

SDKApp definition
new KAppServer({ app, version, title, … })The same keys at the top level. See App definition.
settingssettings, unchanged
kapp.klasses.register(name, schema)klasses
kapp.serverHooks.on(name, handler)A hook and trigger, with a workflow doing what the handler did
kapp.events.on(resource, event, handler)A workflow triggered by the Kustomer event that calls your API through an action, or an outbound webhook
Commands your handlers calledcommands
Client-side KViews (apps-client, apps-react-client)kviews with JSX templates, or your own page in a DynamicCard
kapp.onInstallUsually not needed: the definition creates everything on install. Put remaining setup in the settings page or a workflow.
The CLI's registerPOST /v1/apps/available. See Register and install.
  1. Export what the SDK registers

    Fetch your latest registered version with GET /v1/apps/available/{appVersion}. Copy its listing details, roles, settings and appDetails into your JSON file as a starting point.

  2. Replace each handler

    Work through the table above. Build each workflow in the workflow editor, test it, then export it into the definition. See Build workflows in the editor first.

  3. Keep names and Klasses

    Keep the same app name and Klass names so installed orgs keep their data. Klasses aren't deleted on upgrade, so existing records carry over.

  4. Ship a major version

    Register the definition as a new major version: it removes your server from the app, and orgs should review the change. Once every org has upgraded, you can retire the server.