Choose the right package
Start with the application boundary, not a direct native command. Your product owns its UI, business rules and backend; cApp supplies the selected runtime capabilities and the contracts used to reach them.
| Package | Purpose | Where it belongs |
|---|---|---|
@capp/contracts | Application, route, data, sync and other shared types; route matching and bounded value validation | Browser/app and server |
@capp/app-sdk | Capability discovery, declared requests, local records, sync and typed bridges | Application integration module |
@capp/server-sdk | Server route declarations, gateway verification, receipts and store interfaces | Trusted backend only |
@capp/server-sdk/next | Request/Response route wrapper and explicit public demo response helper | Server route module |
| Portable Solana modules | Thin Sidecar client and network-free payment-verification helpers | App client or trusted verifier, as appropriate |
capp_server | Python core and optional FastAPI adapter | Python backend |
The TypeScript workspace packages in this edition are 0.6.0-alpha.1. These are ESM packages with import exports; do not assume a CommonJS require() entry point. This guide does not assume an npm-registry release exists. Installing an SDK supplies client code and types: it does not install a Sidecar, provision a backend, enrol an installation or prepare a model.
Build and package the workspace SDK
Use the supplied cApp source workspace and its lockfile. The workspace declares Node 20 or newer. Build before packing: a checked-in dist/ may not match the source, and source-only type-checking is not a consumer-package test.
From the cApp repository root:
npm ci
npm run sdk:build
npm run sdk:typecheck
node -e "require('node:fs').mkdirSync('sdk-packages', {recursive:true})"
npm pack --workspace=@capp/contracts --pack-destination ./sdk-packages
npm pack --workspace=@capp/app-sdk --pack-destination ./sdk-packages
npm pack --workspace=@capp/server-sdk --pack-destination ./sdk-packagesFrom an application that sits beside the cApp checkout, install the two app packages together:
npm install ../capp/sdk-packages/capp-contracts-0.6.0-alpha.1.tgz ../capp/sdk-packages/capp-app-sdk-0.6.0-alpha.1.tgz
npm ls @capp/contracts @capp/app-sdkFor a backend, install all three tarballs together. The server package currently declares both contracts and app SDK as dependencies, even when your handler only imports the server entry point:
npm install ../capp/sdk-packages/capp-contracts-0.6.0-alpha.1.tgz ../capp/sdk-packages/capp-app-sdk-0.6.0-alpha.1.tgz ../capp/sdk-packages/capp-server-sdk-0.6.0-alpha.1.tgz
npm ls @capp/contracts @capp/app-sdk @capp/server-sdkAdjust the paths, not the published package names. Keep the generated tarballs and your application's updated lockfile together as the dependency record. A file:vendor/... dependency is another source-controlled option, but each vendored package must include the matching dist/ named by its exports. Copying only src/ does not satisfy those exports. A package version string alone does not establish that two vendored copies have identical bytes.
Verify the consumer with its own type-check and build commands. Check the actual installed package—not only the cApp workspace—before replacing a previously working version. Do not use a browser CDN or an unverified registry package to conceal a failed local installation.
Declare what your application needs
Keep one application-owned integration module. This complete module declares a read-only example route and constructs its typed client; importing it performs no request. Replace the example app ID with your compiled identity before packaging.
import {
createCappClient, defineCappApplication,
type CappRoutePolicyDocument,
} from '@capp/app-sdk';
export const cataloguePolicy: CappRoutePolicyDocument = {
protocol: 'capp.route-policy.v1',
appId: 'com.example.catalogue',
routes: [{
path: '/api/items', methods: ['GET'], capability: 'items.read',
online: true, offline: false, execution: 'remote-only',
}],
};
export const catalogueApplication = defineCappApplication({
appId: 'com.example.catalogue',
requires: { routes: '>=1' },
optional: { data: '>=2', sync: '>=2', 'ai.local': '>=1', links: '>=1' },
routes: cataloguePolicy.routes,
});
export function createCatalogueClient() {
return createCappClient({
application: catalogueApplication,
routePolicy: cataloguePolicy,
strictWebRoutePolicy: true,
});
}Pass routePolicy explicitly. In this SDK, putting routes in application.routes does not automatically populate client.routePolicy. The application definition describes demand; the option configures this client's web request policy. Neither rewrites an already-installed native package's compiled policy.
Start by awaiting client.ready(), inspecting client.compatibility() and making one harmless declared read. Check Response.ok and validate the returned JSON before displaying it. Use the routes walkthrough for data contracts and an observable local write.
Browser, native and server execution
window.capp is the runtime interface; the SDK provides typed access above it. An ordinary browser with no cApp runtime is intentionally web fallback, even when the application definition lists required native capabilities. ready() does not install a runtime or guarantee that a model, wallet or backend is ready. Disable features that require absent capabilities rather than pretending they succeeded.
| Environment | Expected behaviour |
|---|---|
| Ordinary browser | Declared requests can use your web server. No automatic data store, sync queue or native credentials are created by the SDK. |
| Installed application | The selected native runtime owns transport and policy. Its package must include the necessary capabilities and service configuration. |
| Server-side render | There is no browser owner. Do not start an auth flow, local model connection or window watcher while rendering on the server. |
| Unit test | runtime: null deliberately forces web fallback. A supplied runtime/transport double is a test input, not evidence of a native installation. |
Keep the browser client module separate from server SDK imports and private configuration. In a framework with client/server modules, initialise UI watchers after mounting and release them during cleanup. Reopening a view is not permission to duplicate a subscription or active request.
Compatibility and limits
Capability versions are not package versions. This alpha understands *, any, a numeric version or a single numeric comparison such as >=2; it is not a general npm semver-range parser. Do not use ^2, compound ranges or prerelease expressions expecting npm semantics.
Source declarations, installed tarballs, capability versions and native qualification are different evidence. Required capabilities are checked when a runtime exists; optional capabilities still need method and version checks for the feature you use. App client API documents the current readiness and discovery edge cases.
Portable Solana client
The Solana SDK page supplies reviewed ESM modules, their TypeScript declarations and dependency notices. The thin client does not start providers, grant wallet authority or retry submissions. The payment helper does not fetch RPC data or fulfil an order.
Python services
The Python server SDK supplies the capp_server source and optional FastAPI integration without assuming a published Python package. The same backend responsibilities apply: authenticated enrolment, user permissions, durable operation storage and independent validation.
Installation and first-call troubleshooting
| Symptom | Check |
|---|---|
| Missing package, declaration or export | Build before packing; install matching dependencies together; inspect the consumer's npm ls output and lockfile. |
| Source types look newer than installed types | Refresh the package artifact deliberately. A workspace type-check cannot repair an application's installed copy. |
| Route declarations appear ignored | Pass routePolicy as well as application; recompile/repackage when the native contract changes. |
ready() resolves but a feature is unavailable | Inspect the actual bridge and required method. Readiness is not capability installation or service health. |
| Works in browser but not installed | Compare compiled origin, selected services, route admission and native authentication. Do not compensate by copying bearer tokens into JavaScript. |
| Data works only in the native app | Expected unless you deliberately implemented a separate browser store. SDK construction does not create one. |