Publish
Publishing checks
What the store checks in every upload, and how to fix what it refuses.
On this page
Every upload is checked twice: by the CLI before anything leaves your machine, and by the store, which publishes nothing until every one of its checks has passed.
Before the upload leaves your machine
developer upload stops before sending anything when:
ledable.jsonis not valid, or names a file outside the project's folder.- The project's
@ledable/sdkis not a version this CLI builds. The message says whether to update the SDK in the project or the CLI. - The type check fails. It is the strict check
developer checkruns, and it cannot be turned off. - The listing does not fit the limits below: the message names each field that is too long.
developer build does all of this without uploading,
so you can run it as often as you like.
What the store checks
A version number that has already passed is refused at once, with Version already published.
Otherwise the store runs these checks in this order. Each one has the name the CLI prints.
version: the version is newer than every version of the app that passed before.bundle_size: the built bundle is not empty and holds at most 1 MiB (1,048,576 bytes).bundle_pure: the bundle is one self-contained module that loads nothing at run time: noimportorexport … from, noimport(), norequire(). The CLI's build produces such a bundle, so this fails only when code you bundle loads modules itself.assets: every file the app ships is a.webpimage or a.ledfontfont that decodes, at most 4 MiB each and 8 MiB together. Its path inside the project is at most 256 characters of letters, digits,.,_and-, and each folder or file name starts with a letter or a digit. An animated WebP must be made of frames that cover the whole image without blending, which is whatimages convertand the SDK write.manifest: theapp_idinledable.jsonis the app you uploaded to.category:ledable.jsonnames one of the store's categories.sdk: the version was built with an@ledable/sdkthe store still accepts. The check's detail names the oldest one it accepts; update the SDK in the project if yours is older.listing: the listing fits what every store client lays out (the limits are below).media: theiconandscreenshotsare WebP files uploaded with this version.
If all of these pass, the store runs the version once on LEDABLE's servers, the way displays will run it, with your secrets and the hosts your app declares. Each step has 10 seconds:
settings:settingsreturns settings that every client can show. What it returns is kept with the version, and is used wheneversettingsfails later.preview:previewreturns an image.render: one render with every setting at its default, for a 64×32 display, in English and in UTC, returns an image. A render that reports a failure, throws, or returnsimage: nullfails this check. When a setting isrequired, it has no default to render with, so no render is made and the check passes withnot rendered, needsand the settings' keys.credentials: if the app has a credential setting, its bundle exportsverifyCredential.
If the version cannot be run at all, a single runtime check fails instead of the last four, with
the reason.
Because the run is real, the services your app reads must answer while you upload, and every secret the version declares must have a value.
Listing
The store checks the listing against these limits, counted in characters. The CLI checks the same limits before it builds.
| Field | Limit |
|---|---|
name | 30 characters |
description | 120 characters |
The file readme names | 4000 characters |
tags | 5 tags of at most 20 characters each |
screenshots | 6 images |
The fields themselves are described in The project and the
ledable.json reference.
Reading the result
When every check passes, developer upload prints the published version with each check and
what it found. Here it is for the example app of Accounts and credentials,
shortened:
{
"version": {
"version": "1.0.0",
"state": "ready",
"bundle_size": 65366,
"assets_size": 416625,
"checks": [
{
"name": "version",
"ok": true,
"detail": "1.0.0 is the first version"
},
{
"name": "bundle_size",
"ok": true,
"detail": "65366 bytes, limit 1048576"
},
{
"name": "render",
"ok": true,
"detail": "not rendered, needs token"
},
{
"name": "credentials",
"ok": true,
"detail": "checks token"
}
],
"created_at": 1791216000
}
}When a check fails, the command exits with status 1 and prints one JSON error on stderr, as every
command does. Its message starts with Version failed publishing checks and then lists each check
that ran, one per line, ok or FAIL with its detail:
Version failed publishing checks
FAIL version: 1.0.0 must be newer than 1.1.0
ok bundle_size: 65366 bytes, limit 1048576
ok bundle_pure: bundle must be a self-contained ESM module without imports
ok assets: 9 assets, 416625 bytes
ok manifest: GitLab To-Dos
ok category: productivity
ok sdk: @ledable/sdk 0.1.0, minimum 0.1.0
ok listing: fits
ok media: 0 listing imagesWhen any of the first nine checks fails, the version is not run, so the last four do not appear.
The store keeps every attempt:
developer versions lists them with their checks,
and developer status shows the failed checks of the
latest upload under last_failure.
Fix and upload again
A version that failed was not published. Fix the problem and upload the same version number again; the new attempt replaces the failed one.
A version that passed is published for good and can never be uploaded again, even if you change
nothing. To ship a change, raise version in ledable.json and upload that.