DropletManifest

The contents of a droplet's droplet.json.

struct DropletManifest

{
  "id": "worldclock",
  "name": "World Clock",
  "version": "1.0.0",
  "summary": "Every timezone you care about, on the shelf",
  "category": "Productivity",
  "kit": { "abi": 1, "minAPI": "1.0.0" },
  "minAppVersion": "15.3.0",
  "capabilities": ["shelf-read"],
  "surfaces": ["shelf-widget", "settings-pane"],
  "icon": "WorldClock.icon",
  "creator": {
    "name": "Jane Doe",
    "kind": "community",
    "url": "https://jane.example",
    "avatar": "Creator.png"
  },
  "source": {
    "repository": "https://github.com/jane/worldclock-droplet",
    "commit": "9f1c2ab5c0e4d3f6a7b8c9d0e1f2a3b4c5d6e7f8",
    "license": "MIT"
  }
}

Initializers

init(from:)

init(from decoder: Decoder) throws

init(id:name:version:summary:description:category:kit:minAppVersion:capabilities:surfaces:icon:creator:source:screenshots:keywords:)

init(id: DropletID, name: String, version: SemanticVersion, summary: String, description: String? = nil, category: String, kit: DropletKitRequirement, minAppVersion: String, capabilities: [DropletPermission] = [], surfaces: [DropletSurface], icon: String, creator: DropletCreator, source: DropletSource? = nil, screenshots: [String] = [], keywords: [String] = [])

Type properties

summaryCharacterLimit

static let summaryCharacterLimit: Int

The longest summary the Store's row renders without truncating.

Properties

capabilities

let capabilities: [DropletPermission]

Capabilities the droplet needs. The user sees these before installing, so ask for what you use and nothing else — a long list is the single biggest reason a submission is sent back.

category

let category: String

Store category, for example "Productivity" or "Media".

creator

let creator: DropletCreator

Who made it.

description

let description: String?

The long description on the detail page. Markdown is not rendered; keep it plain paragraphs separated by blank lines.

icon

let icon: String

Filename of the Icon Composer document, relative to the droplet's root. Required, and it must be a real .icon document rather than a PNG — see DropletIcon.

id

let id: DropletID

Stable identifier. Must match id and the bundle's DroppyDropletID. Lowercase for public submissions.

keywords

let keywords: [String]

Search keywords beyond the name and summary.

kit

let kit: DropletKitRequirement

Which DroppyKit this was built against.

minAppVersion

let minAppVersion: String

Oldest Droppy this droplet runs in, for example "15.3.0".

name

let name: String

Display name, sentence case.

screenshots

let screenshots: [String]

Screenshot filenames, relative to Assets/. The first is the one the Store shows on the droplet's card.

source

let source: DropletSource?

Where the source lives. Required for community droplets; omitted for first-party ones, whose source is not public.

summary

let summary: String

One line, shown under the name in the Store. Aim for under 60 characters so it does not truncate at the Store's row width.

surfaces

let surfaces: [DropletSurface]

Surfaces this droplet provides.

version

let version: SemanticVersion

Droplet version, major.minor.patch. Numeric-dotted only: a pre-release tag cannot be published, because the fleet's catalog decode is strict and would refuse the whole catalog.

Methods

validate(submission:)

func validate(submission: Bool = false) throws

Checks everything that can be checked from the manifest alone.

Pass submission: true for a community submission, which adds the rules that only apply to third-party droplets: a lowercase id, a declared public repository, and creator.kind == .community.

This is the same check Scripts/validate-droplet.sh runs, so a droplet that validates locally validates at intake.