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] = [])

init(id:name:version:summary:description:category:kit:minAppVersion:minMacOS: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, minMacOS: String?, capabilities: [DropletPermission] = [], surfaces: [DropletSurface], icon: String, creator: DropletCreator, source: DropletSource? = nil, screenshots: [String] = [], keywords: [String] = [])

Creates a manifest that names a minimum macOS. A second initializer rather than a defaulted parameter, so the 1.0 initializer keeps its symbol.

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

The Store section this droplet appears under: one of DropletCategory's values, matched case-insensitively, so "Productivity" and "productivity" are the same shelf.

Kept as a String rather than the enum so a manifest written against a later SDK still decodes here; validate(submission:) is what refuses a value no Store section can show.

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

minMacOS

let minMacOS: String?

Oldest macOS this droplet runs on, for example "26.0", when it needs more than Droppy does. The Store does not offer it to an older Mac and Droppy does not load it there. Omit it to run wherever Droppy runs. Since 1.12.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.

Type methods

isNumericDotted(_:)

static func isNumericDotted(_ version: String) -> Bool

Whether a version string is components of digits separated by dots, and nothing else.

The rule everywhere: DropletHostDescriptor.numericVersionCompare reads each component as an integer and an unparseable one as zero, so anything that is not this compares as something other than what it reads as.

isReleaseVersion(_:)

static func isReleaseVersion(_ version: String) -> Bool

Whether a release artifact has the exact three-component version the Store and repository updater publish.

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.