asuka.json
ReferenceEpisode 21

第弐拾壱話

asuka.json

Every key of an app's asuka.json, its type, its default and what it does on each platform.

asuka.json, in the app's directory, says what the platforms and the stores need to know of the app: its name and ID, its icon, the links and files it opens, its signing keys. asuka dev, asuka build and asuka publish read it; asuka dev reads it as it starts, so stop it and run it again after a change.

Every key is optional, and an app without the file builds and runs with the defaults. A key Asuka doesn't know is ignored, so check a key's spelling when it seems to do nothing. A value Asuka can't take stops the build, saying which and what it wants (asuka.json: accent "red" (want #rrggbb or #rrggbbaa)). Paths are relative to the app's directory.

This page lists every key. Shipping tells how they come together for a release, and each guide linked below tells more of what its keys do.

JSON
{
  "name": "Notes",
  "id": "com.example.notes",
  "version": "1.2.0",
  "build": 7,
  "icon": "icon.png",
  "accent": "#7c3aed",
  "scheme": "notes",
  "links": ["notes.example.com"],
  "fileTypes": [{ "name": "Notes Document", "extensions": ["note"] }],
  "shareTarget": true,
  "splash": { "image": "logo.png", "background": "#ffffff", "darkBackground": "#000000" },
  "ios": {
    "team": "ABCDE12345",
    "usage": { "NSCameraUsageDescription": "To scan your receipts." }
  },
  "android": { "keystore": "upload.jks", "keyAlias": "upload", "dynamicColor": true },
  "linux": { "summary": "Write things down", "categories": ["Office"], "license": "MIT" },
  "updates": { "publicKey": "…", "github": "you/notes" }
}

The app

These apply on every platform the key means something on.

Key Type Default What it is
name string the directory's name The app's name: under its icon, in the Mac's menu bar, the window's title on Windows, the launcher's on Linux, the web page's title. It names the build's files too (Notes.app, Notes.exe).
id string dev.asuka.<directory> The bundle ID on iOS and the Mac, the application ID on Android and Linux (its desktop file, icon, D-Bus name and data directory), the AppUserModelID on Windows. Change it before the first release: the stores and the systems know the app by it. On Linux it must be letters, digits, _ and -, in two parts or more, none starting with a digit.
version string 1.0 The version users see.
build integer 1 The build's number, which must grow with each upload. asuka publish numbers a build one above the store's highest itself, so this is only where it starts. Windows's file version is version and build together (1.2.0.7).
icon path none: the platform's generic icon A square PNG, 1024×1024, without transparency for iOS. Each build makes the sizes its platform wants. The App Store needs one.
accent color the platform's "#rrggbb" or "#rrggbbaa": the tint on iOS, the seed of the Material 3 color scheme on Android, the color of Accent, filled buttons and links on the Mac (AppKit's own controls keep the user's), the controls' accent on Windows and libadwaita's on Linux, the page's and the manifest's theme_color on the web.
orientations strings both "portrait", "landscape": the orientations the app takes on a phone. iPads take all four, as Split View and Stage Manager need, and Android 16 ignores it on tablets and foldables.
scheme string none The app's URL scheme: notes:// URLs open it, and ui.OnOpenURL gets them, on iOS, Android, the Mac, Windows and Linux. Letters, digits, +, - and ., a letter first. See Deep links.
links strings none Domains, as example.com, whose https links open the app: iOS's universal links and Android's App Links. The domain serves the association file. See Deep links.
fileTypes objects none The kinds of files the app opens. See fileTypes.
shareTarget true or object off The app in other apps' share sheets, on iOS and Android. See shareTarget.
splash object none The launch screen, on iOS and Android. See splash.
widgets objects none Home screen widgets, on iOS and Android. See widgets.
shortcuts objects none Actions for Siri, Spotlight and the launcher, on iOS and Android. See shortcuts.
nfc object none What asuka/sdk/nfc's tags need: iOS's AIDs and FeliCa system codes, the tags that open the app on Android. See nfc.
background boolean false On the desktop, an app that lives in the tray, as app.RunInBackground makes it: no window at launch, kept running with none, and on the Mac no Dock icon from launch (LSUIElement). See Apps in the background.
singleInstance boolean true On Windows and Linux, a second launch hands its arguments to the running app (app.OnSecondInstance, its files to ui.OnOpenFiles) and quits. false runs the app as often as it's started. The Mac runs an app once either way. See One instance.
i18n object locales, when there Where the app's catalogs are. See i18n.
updates object none A desktop app's signed updates. See updates.
ios object The iOS build's, and some of the Mac's. See ios.
mac object The Mac build's profiles. See mac.
applePay object none {"merchantIds": ["merchant.com.example"]}: the merchant IDs Apple Pay pays with (asuka/sdk/pay), in the in-app-payments entitlement of an iOS or Mac app that imports the package. See Wallet payments.
android object The Android build's. See android.
linux object What a Linux build says of the app. See linux.
web object The web build's. See web.
bluetooth object What an app of asuka/sdk/bluetooth asks beyond the package's needs: the background, the location from scans. See bluetooth.

A Windows build needs nothing beyond these: its signing certificate is given in the environment (see Shipping).

fileTypes

The kinds of files the app opens, from the file manager, a mail's attachment or "Open With"; ui.OnOpenFiles gets them. Each is an object:

JSON
"fileTypes": [
  { "name": "Markdown Document", "extensions": ["md", "markdown"], "role": "viewer" },
  { "name": "Notes Document", "extensions": ["note"], "icon": "note.png" }
]
Key Type Default What it is
extensions strings required The files' name extensions, without the dot: "md", "tar.gz".
name string the first extension in capitals and "Document" What the files are, as the system shows it.
mimeTypes strings those Asuka knows for the extensions Their MIME types. For an extension Asuka doesn't know, the type is the app's own: application/x-<app>-<extension>.
uti string the system's for a known extension, else <id>.<extension> Their Uniform Type Identifier on Apple's platforms. One under the app's ID is the app's own type: exported, and the app is its files' owner. Another the system may not know is imported.
conformsTo strings public.data, public.content The UTIs an exported or imported type conforms to. public.plain-text makes Quick Look and text editors take it.
role string "editor" "editor" or "viewer": what the app does with them (CFBundleTypeRole on the Mac and iOS).
icon path the system's, or the app's A square PNG, the files' icon on the Mac, Windows and Linux.

Each platform declares them its own way: Info.plist's CFBundleDocumentTypes on the Mac and iOS, intent filters on Android, the user's registry on Windows as the app starts, the desktop file and a shared-mime-info package on Linux, the manifest's file_handlers on the web. See Shipping and Opening files.

shareTarget

The app in other apps' share sheets, on iOS and Android; ui.OnShare gets what's shared. true takes texts and web links; an object says what else:

JSON
"shareTarget": { "types": ["text", "image/*", "video/*"], "max": 10 }
Key Type Default What it is
types strings ["text"] "text" (texts and web links), and files by MIME type: "image/*", "video/*", "audio/*", "application/pdf", "*/*" for any.
max integer 1 How many files it takes at once, 1 or more.

On iOS it's a share extension in the app, with its own bundle ID (the app's plus .share), which a release signs with ios.shareProfile. One that takes files also needs the App Group group.<id>. See Shipping and Shares from other apps.

splash

The launch screen on iOS and Android: an image in the middle of a color, from the tap on the icon until the app's first frame (or splash.Hide). The desktops and the web have none.

JSON
"splash": { "image": "logo.png", "size": 96, "background": "#4A63B5", "darkBackground": "#1B2440" }
Key Type Default What it is
image path none A square PNG, a logo.
size integer 120 The image's width in points (dp), at most 160, the most Android 12's icon circle holds.
background color "#ffffff" "#rrggbb", in light mode.
darkBackground color background "#rrggbb", in dark mode.

See The launch screen.

widgets

The app's home screen widgets, on iOS and Android; widget.Set fills them from the app's Go code.

JSON
"widgets": [{ "kind": "today", "name": "Today", "description": "What's next", "sizes": ["small", "medium", "rectangular"] }]
Key Type Default What it is
kind string required The widget's name for widget.Set: letters, digits and _, a letter first, each widget's its own.
name string kind What the widget gallery calls it.
description string none What the widget gallery says of it.
sizes strings ["small", "medium"] small, medium, large, and iOS's extraLarge (iPad) and lock screen circular, rectangular and inline.

On iOS the widgets are an extension with its own bundle ID (the app's plus .widgets), which a release signs with ios.widgetProfile. See Home screen widgets.

shortcuts

Actions the system offers for the app, at most ten: iOS's App Shortcuts (Siri, Spotlight, the Shortcuts app, the Action button) and Android's launcher shortcuts. Each opens the app with its URL, for ui.OnOpenURL.

JSON
"shortcuts": [{ "id": "newNote", "title": "New Note", "url": "notes://new", "symbol": "square.and.pencil", "phrases": ["New note in ${app}"] }]
Key Type Default What it is
id string required Letters, digits and _, a letter first, each shortcut's its own.
title string required What the system shows.
url string required What the app is opened with: a URL of its scheme, or one of its links.
symbol string none An SF Symbol's name, as ui.Symbol takes it.
phrases strings "<title> in ${app}" What Siri hears, each with ${app}, the app's name. iOS only.

See Shortcuts.

nfc

What asuka/sdk/nfc needs of the platforms beyond its permissions, for an app that imports it (an app that doesn't gets none of it):

JSON
"nfc": {
  "iso7816": ["D2760000850101"],
  "felica": ["8008"],
  "ndef": [{ "uri": "https://example.com/t/" }, { "mime": "application/vnd.example.ticket" }, { "external": "example.com:ticket" }],
  "tech": [["IsoDep"], ["NfcA", "MifareUltralight"]]
}
Key Type Default What it is
iso7816 strings none The ISO 7816 applications (AIDs: 5 to 16 bytes, in hex) iOS selects as it finds a card, in order: Info.plist's com.apple.developer.nfc.readersession.iso7816.select-identifiers. A session with Poll finds only the cards with one of them.
felica strings none The FeliCa system codes (4 hex digits, not FFFF) iOS polls for: com.apple.developer.nfc.readersession.felica.systemcodes, without which a session that polls FeliCa fails.
ndef objects none The tags that open the app on Android by their message's first record (NDEF_DISCOVERED), each one of uri (its scheme, host and path prefix; the URI comes to ui.OnOpenURL), mime (a MIME type; text records are text/plain) and external (domain:type); the tag comes to nfc.OnOpen.
tech lists of strings none The tags that open the app on Android by their technologies (TECH_DISCOVERED): each list, the android.nfc.tech classes a tag must all have (IsoDep, NfcA, MifareUltralight...).
required boolean false Makes the app one for phones with NFC alone: Google Play doesn't offer it to others.

See NFC tags.

i18n

Where the app's message catalogs are. An app with catalogs in a locales directory needs none of it.

JSON
"i18n": { "dir": "translations", "source": "ja" }
Key Type Default What it is
dir path locales The directory of catalogs, one per language, named after its BCP 47 tag: en.json, pt-BR.json, zh-Hans.json.
source string en, or the only catalog there is The language the app is written in: its catalog has every message, and the others fall back to it.

See Languages.

updates

A desktop app's updates: the key they're signed with, and where they're published. asuka update keygen makes the key pair and prints this object.

JSON
"updates": { "publicKey": "…the contents of asuka-update.pub…", "github": "you/notes" }
Key Type Default What it is
publicKey string required asuka-update.pub's contents, built into the app: it takes only updates signed with the secret key.
github string "owner/name": a public repository whose releases, tagged v1.2.0, hold the updates.
tagPrefix string "v" The releases' tags' prefix. Another, as "desktop-v", lets the repository's latest release be another's: apps then find the newest tagged with it through the GitHub API.
url string Instead of github: an HTTPS directory that serves the files (an S3 or R2 bucket, a CDN); apps read <url>/update-<target>.json.
feed string none An HTTPS server of yours that apps ask instead, its URL with {target}, {version} and {channel}. It needs url, where the files are.
s3 object none The bucket that serves url, which asuka publish uploads to: bucket (required), prefix (its directory; default its root), region (default AWS_REGION, else AWS_DEFAULT_REGION, else us-east-1), endpoint (R2's, MinIO's; default Amazon S3), pathStyle (default: with endpoint, or a bucket name with dots).
privateKey path none The secret key's path, for builds on your machine (~/ is the home directory).
changelog path CHANGELOG.md, when there is one A Markdown file whose ## 1.2.0 section is the release notes.
deltas integer 3 How many versions before get a delta update, a download of what changed alone; 0, none.

It needs either github or url, not both. See Updates.

ios

The iOS build's. team is the Mac build's team too, and usage's purpose strings go in the Mac's Info.plist as well.

Key Type Default What it is
team string none The Apple Developer team ID that signs the app (ABCDE12345).
profile string the best match installed The app's provisioning profile: its path, name or UUID. --profile overrides it.
shareProfile string the best match installed The share extension's (shareTarget), for the ID <id>.share.
widgetProfile string the best match installed The widget extension's (widgets), for the ID <id>.widgets.
notificationProfile string the best match installed The Notification Service Extension's (push.Rewrite), for the ID <id>.notification.
usage object the packages' own Purpose strings of protected resources, by Info.plist key: {"NSCameraUsageDescription": "To scan your receipts."}. The packages the app imports give generic ones; write your own.
infoPlist object none String keys added to Info.plist.
backgroundModes strings none Added to Info.plist's UIBackgroundModes: "audio", to record and play with the screen locked.
iphoneOnly boolean false Leaves iPad out: the app runs there as an iPhone app, in a phone-sized window.
storekit string none A StoreKit configuration file (Xcode's .storekit) that asuka dev's simulator build sells from, as Xcode's scheme does: see In-app purchases.
nonExemptEncryption string "no" What a build says of its encryption (ITSAppUsesNonExemptEncryption), a legal statement that's yours to make: "no", "yes", or "ask", which says nothing, so App Store Connect asks at each upload.
collected objects none The data the app collects, for its privacy manifest (see below).
appStoreConnect object The App Store Connect API key asuka publish uploads with: keyId, issuerId (none for an individual key) and key, the .p8's path (default: AuthKey_<keyId>.p8 in ~/.appstoreconnect/private_keys, as altool looks). See Publishing.

Each of collected is a kind of data, by Apple's names without their prefixes, for the privacy manifest Asuka writes (an app's own ios/PrivacyInfo.xcprivacy replaces it, and this with it):

JSON
"collected": [{ "type": "EmailAddress", "linked": true, "tracking": false, "purposes": ["AppFunctionality"] }]
Key Type What it is
type string "EmailAddress" is NSPrivacyCollectedDataTypeEmailAddress.
linked boolean Tied to the user's identity.
tracking boolean Used to track them.
purposes strings "AppFunctionality" is NSPrivacyCollectedDataTypePurposeAppFunctionality.

See Shipping.

mac

What a Mac build signs the app with; its team is ios.team.

Key Type Default What it is
profile string ASUKA_MAC_PROFILE, else, for an app that needs one, the best match installed A Developer ID (or development) provisioning profile's path, name or UUID, which push, Sign in with Apple, App Attest and Apple Pay need.
appStoreProfile string the best match installed A Mac App Store profile, for --appstore.

--profile and ASUKA_MAC_PROFILE override them. See Shipping.

android

The Android build's.

Key Type Default What it is
keystore path none The upload key's keystore, which signs a release. Its password is ASUKA_KEYSTORE_PASSWORD's, and the key's ASUKA_KEY_PASSWORD's (default: the keystore's).
keyAlias string none The upload key's alias in the keystore.
dynamicColor boolean false Takes the colors from the user's wallpaper (Android 12 and later), as Material apps do; accent is the seed elsewhere.
permissions strings the packages' own Permissions added to the manifest: "android.permission.CAMERA". "<name>:28" asks for one up to Android 9 (API 28) only. The packages the app imports add those they need.
googleServices path none The Firebase project's google-services.json, for asuka/sdk/push.
mapsKey string none A Google Maps Platform API key (Maps SDK for Android), for asuka/sdk/maps.
serviceAccount path none The Google Cloud service account's JSON key asuka publish uploads to Google Play with. Keep it out of the repository.

See Shipping.

linux

What a Linux build's desktop file and AppStream metainfo say of the app: what launchers, software centers and Flathub show. Flathub and the software centers want the summary, description, license and developer.

Key Type Default What it is
summary string none A line saying what the app does.
description string none A few paragraphs, separated by blank lines.
categories strings ["Utility"] freedesktop.org's main categories: Utility, Office, Development, Network...
keywords strings none More words a launcher finds the app by.
license string none The app's license, as an SPDX expression: MIT, GPL-3.0-or-later, LicenseRef-proprietary.
developer string none The developer's name.
homepage string none The app's web page.
flatpakRuntime string a recent one The GNOME runtime's version the Flatpak manifest asks for, 46 or later.

See Shipping.

web

The web build's.

Key Type Default What it is
vapidPublicKey string none The app server's VAPID public key (base64url), with which the browser subscribes to Web Push for asuka/sdk/push.
base string "/" The path the site is served at ("/app/" for https://example.com/app/): the page's <base href>, under which a router's hrefs are its addresses. asuka build --base overrides it. See Addresses and history.

See Web Push.

bluetooth

What an app that imports asuka/sdk/bluetooth asks for beyond what the package gives it (its permissions and purpose string). It does nothing for an app that doesn't import the package.

JSON
"bluetooth": { "background": ["central"], "location": false }
Key Type Default What it is
background strings none The roles the app keeps in the background. "central": iOS's bluetooth-central mode, with state restoration (bluetooth.OnRestore), and the receiver of Android's background scan (ScanOptions.Background). "peripheral": iOS's bluetooth-peripheral mode.
location boolean false The app finds where the user is from its scans (beacons): Android's BLUETOOTH_SCAN without neverForLocation, and the location permission bluetooth.Request then asks for too (iOS: NSLocationWhenInUseUsageDescription).

See Bluetooth.

The environment

Secrets stay out of asuka.json: give them in the environment, which CI does from its secrets. These also override the keys they name.

Variable What it is
ASUKA_KEYSTORE, ASUKA_KEY_ALIAS Over android.keystore and android.keyAlias.
ASUKA_KEYSTORE_PASSWORD, ASUKA_KEY_PASSWORD The keystore's password, and the key's when it differs.
ASUKA_ASC_KEY_ID, ASUKA_ASC_ISSUER_ID, ASUKA_ASC_KEY Over ios.appStoreConnect; ASUKA_ASC_KEY is the .p8's path or its text.
ASUKA_PLAY_SERVICE_ACCOUNT Over android.serviceAccount: the key's path or its JSON.
ASUKA_MAC_PROFILE Over mac.profile.
ASUKA_UPDATE_PUBLIC_KEY, ASUKA_UPDATE_URL Over updates.publicKey and updates.url (which then replaces github).
ASUKA_UPDATE_PRIVATE_KEY The updates' secret key itself, or its path, over updates.privateKey.
ASUKA_WINDOWS_CERT, ASUKA_WINDOWS_CERT_PASSWORD, ASUKA_WINDOWS_TIMESTAMP A Windows build's signing certificate (a .pfx), its password and the timestamp servers, which asuka.json doesn't hold. See Shipping.