# Legacy Apps SDK

> 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.

Source: https://developer.kustomer.com/docs/apps/legacy-apps-sdk

> **Deprecated:** The Apps SDK is no longer developed. It's kept running for existing apps, but new apps should use [JSON app definitions](https://developer.kustomer.com/docs/apps/app-definition), which Kustomer runs for you with no server to host.

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

| Package                       | What it did                                                                                        |
| ----------------------------- | -------------------------------------------------------------------------------------------------- |
| `@kustomer/apps-server`       | `KAppServer`, an Express app that registers the definition and routes hooks and events to handlers |
| `@kustomer/apps-client`       | A framework-agnostic library for client-side KViews                                                |
| `@kustomer/apps-react-client` | React components for KViews in Kustomer's design system, built on `apps-client`                    |
| `@kustomer/apps-common`       | Shared types (such as `SettingsManifest`) and API helpers used by the client and server            |
| `@kustomer/apps-tokens`       | Design tokens for the React components                                                             |
| `@kustomer/apps-cli`          | Scaffolds new apps (`npx @kustomer/apps-cli new <name>`) and registers them                        |

## How an SDK app looks

```ts title="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
```

```ts title="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`](https://developer.kustomer.com/docs/apps/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.

| SDK                                                     | App definition                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `new KAppServer({ app, version, title, … })`            | The same keys at the top level. See [App definition](https://developer.kustomer.com/docs/apps/app-definition).                                                                                                                                                                                                                                               |
| `settings`                                              | [`settings`](https://developer.kustomer.com/docs/apps/settings), unchanged                                                                                                                                                                                                                                                                                   |
| `kapp.klasses.register(name, schema)`                   | [`klasses`](https://developer.kustomer.com/docs/apps/klasses)                                                                                                                                                                                                                                                                                                |
| `kapp.serverHooks.on(name, handler)`                    | A [`hook`](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#hooks-get-data-in) and [`trigger`](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#triggers-name-the-event), with a [workflow](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#workflows-wire-it-together) doing what the handler did |
| `kapp.events.on(resource, event, handler)`              | A workflow triggered by the [Kustomer event](https://developer.kustomer.com/docs/events/event-catalog) that calls your API through an [action](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#actions-call-your-api), or an [outbound webhook](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#outbound-webhooks)   |
| Commands your handlers called                           | [`commands`](https://developer.kustomer.com/docs/apps/kviews#call-apis-with-commands)                                                                                                                                                                                                                                                                        |
| Client-side KViews (`apps-client`, `apps-react-client`) | [`kviews`](https://developer.kustomer.com/docs/apps/kviews) with JSX templates, or your own page in a [`DynamicCard`](https://developer.kustomer.com/docs/apps/kviews#embed-your-own-ui)                                                                                                                                                                     |
| `kapp.onInstall`                                        | Usually not needed: the definition creates everything on install. Put remaining setup in the settings page or a workflow.                                                                                                                                                                                                                                    |
| The CLI's `register`                                    | `POST /v1/apps/available`. See [Register and install](https://developer.kustomer.com/docs/apps/register-and-install).                                                                                                                                                                                                                                        |

#### Export what the SDK registers

Fetch your latest registered version with [`GET /v1/apps/available/{appVersion}`](https://developer.kustomer.com/api/apps-platform/get-available-app). Copy its listing details, `roles`, `settings` and `appDetails` into your JSON file as a starting point.

#### 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](https://developer.kustomer.com/docs/apps/workflows-actions-triggers#build-workflows-in-the-editor-first).

#### 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.

#### 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.

> **For agents migrating an SDK app:** Read the `KAppServer` options first: they map one-to-one onto top-level definition keys. Then search the code for `klasses.register`, `serverHooks.on`, `events.on` and `onInstall` to find the components and logic that have to move into the definition.
