Skip to main content

App manifest

Use manifest.json to describe your extension for Kittl: listing fields, the embed HTML entrypoint, requested SDK scopes, and optional OAuth providers. The Kittl API validates this file against the shape below when you create or update a draft version; the CLI only checks that it is a valid JSON object.

Manifest schema​

Field names are camelCase in JSON (for example authorizationUrl, not authorization_url).

type Scope =
| 'design:state:read'
| 'design:state:write'
| 'export:bypass'
| 'uploads:create'
| 'fonts:read'
| 'fonts:write'
| 'fonts:read:global'
| 'fonts:write:global'
| 'uploads:global:read'
| 'data:mockups:read'
| 'ai:credit:spend'
| 'workspace:state:read'
| 'workspace:state:write';

type OAuthProvider = {
authorizationUrl: string;
clientId: string;
tokenUrl: string;
scope?: string;
accessType?: string;
customFieldMappings?: Record<string, unknown>;
};

// App Directory category slugs.
type Category =
| 'ai-gen'
| 'image-editing'
| 'typography'
| 'elements'
| 'mockups'
| 'commerce'
| 'marketing'
| 'workflow';

type ExtensionManifest = {
$schema?: string;
displayName: string;
icon: string;
tagline: string;
// 1-3 image paths shown in the App Directory listing (omit if none).
screenshots?: string[];
// App Directory category. Array is future-proofing; exactly one for now.
tags?: Category[];
installPage: {
description: string;
coverImage: string;
termsAndConditionsLink: string;
privacyPolicyLink: string;
};
config: {
scopes: Scope[];
embed: {
editorContentPanel: {
path: string;
};
editorScriptRunner?: {
path: string;
};
sharedFileBrowser?: {
path: string;
};
dashboardStandalonePage?: {
path: string;
};
};
appDevelopment?: {
local: {
requireHTTPS?: boolean;
port?: number;
};
};
oauthProviders?: Record<string, OAuthProvider>;
};
};

config.scopes is required. If you want no permissions, set it to an empty array ([]). With an empty scope set, many SDK calls will be denied by scope checks.

export:bypass allows direct export without showing the export modal. It also requires developer organization approval; declaring the scope alone does not grant access. Opening the host export modal with kittl.export.showExportModal() requires design:state:read instead. See Export API.

Removed field names

The deprecated mainAppPanel and scriptRunner fields are no longer supported. Use editorContentPanel and editorScriptRunner instead.

Complete example​

{
"$schema": "https://api.kittl.com/extensions/manifest/schema.json",
"displayName": "My extension",
"icon": "icon.svg",
"tagline": "My extension for Kittl.",
"screenshots": ["screenshot-1.png", "screenshot-2.png"],
"tags": ["commerce"],
"installPage": {
"description": "Install My extension to use it in Kittl.",
"coverImage": "icon.svg",
"termsAndConditionsLink": "https://example.com/terms",
"privacyPolicyLink": "https://example.com/privacy"
},
"config": {
"scopes": ["design:state:read", "design:state:write"],
"embed": {
"editorContentPanel": {
"path": "index.html"
}
},
"appDevelopment": {
"local": {
"requireHTTPS": true,
"port": 5173
}
},
"oauthProviders": {
"myProvider": {
"authorizationUrl": "https://provider.example.com/oauth2/authorize",
"clientId": "client-id-from-provider",
"scope": "assets.read assets.write",
"accessType": "offline",
"tokenUrl": "https://provider.example.com/oauth2/token"
}
}
}
}

Manifest location​

Place manifest.json at the root of your app project (same level as the output/ directory), not inside output/.

Field notes​

  • displayName, tagline, icon: short listing fields for your extension.
  • icon: must be an SVG file (for example icon.svg); other formats are rejected on upload.
  • screenshots: optional array of 1-3 image paths (relative to the built artifact root), shown in the App Directory listing. Omit it if you have none; an empty array is rejected.
  • tags: optional App Directory category (one of the Category values above). Array-shaped to allow multiple later, but currently exactly one.
  • installPage: longer description, cover art, and links shown in the install flow (termsAndConditionsLink and privacyPolicyLink are required).
  • config.embed.editorContentPanel.path: HTML entrypoint for the main panel in the editor content area (next to the canvas). Required. The path is interpreted relative to the built artifact root (the contents you upload), for example index.html next to your bundled assets.
  • config.embed.editorScriptRunner.path: optional HTML entrypoint for a headless runner — a hidden iframe that runs background logic (AI pipelines, data sync, etc.) with full SDK access but no visible UI.
  • config.embed.sharedFileBrowser.path: optional HTML entrypoint for a file browser panel. Extensions can register custom tabs in the Kittl upload panel to show their own file browsing UI. See the File Browser guide for implementation details.
  • config.embed.dashboardStandalonePage.path: optional HTML entrypoint for a standalone page on the Kittl dashboard (outside the editor).
  • config.scopes: SDK permissions your extension requests. See SDK scopes.
  • config.oauthProviders: map of provider id to OAuth endpoints; the key is the provider string you pass to kittl.auth. scope and accessType are optional in the manifest if your provider does not need them.
  • config.appDevelopment.local: optional local-dev hints (requireHTTPS is useful when a provider expects a secure origin; port can match your dev server).

Development helpers​

JSON Schema for editors

The canonical JSON Schema for extension manifests is published at https://api.kittl.com/extensions/manifest/schema.json.

Add a $schema field in manifest.json so your editor can validate and autocomplete against it:

{
"$schema": "https://api.kittl.com/extensions/manifest/schema.json"
}