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.