App Store Submission
Package, authenticate, and publish a Rome App to the Rome App Store.
Agent-readable version: Markdown · llms.txt
Rome does not currently have an in-instance submit form for app authors. The
Rome dashboard App Store is the browse/install surface. Publishing is done
through the Rome App Store API, usually via the rome CLI (shipped with
@rome-os/app-web-sdk).
The short version — first, build + pack via a source-mode install into your
running Rome instance. The daemon runs the app's own build (if it declares one)
and writes the packed artifact to <path-to-app-source>/.rome/artifact:
// system:app_management
{ "op": "install", "source": { "mode": "source", "path": "<path-to-app-source>" } }Then authenticate and publish:
# 2. Authenticate to the Rome App Store.
export ROME_TOKEN=<token-from-store-settings>
export ROME_STORE_HOST=https://romeos.cc
# 3. Publish the artifact to the store.
rome publish <path-to-app-source>/.rome/artifactUse rome publish --dry-run before the real publish when you want to verify
the bundle hash and size without uploading.
What Gets Published
The store hosts immutable app versions. A successful publish creates or updates
a listing and writes one live version for the app.yaml version in the bundle.
There is no separate review queue in the current implementation: if the API
accepts the upload, the version is live.
The directory passed to rome publish must contain app.yaml. For a
release, prefer passing the packed artifact a source-mode install writes to
<app>/.rome/artifact, not the raw development directory. The packed
artifact is the same shape used by local installs.
Manifest Checklist
Before publishing, check the app identity fields in app.yaml:
formatVersion: 2
id: your-app
name: Your App
version: 1.0.0
description: Short listing summary
icon: assets/icon.svgRequired by the store:
idversiondescription
Recommended for public listings:
nameicon.rome_store/rome_store.yaml.rome_store/assets/*for store-only images/videos
version must be strict SemVer. Publishing another version for the same listing
requires a strictly higher version than the listing's current high-water mark.
Store Listing Fields
Public store listing pages derive canonical URLs, robots policy, Open Graph,
Twitter card metadata, JSON-LD, and sitemap entries from Rome Cloud. App authors
can supply richer store content in .rome_store/rome_store.yaml:
title: Morning Brief for Rome
description: Get a daily AI-generated briefing from calendar, inbox, and reminders.
long_description: |
Morning Brief turns your Rome into a calm daily planning surface.
categories:
- Productivity
homepage: https://example.com
repository: https://github.com/you/morning-brief
keywords:
- daily briefing
- calendar assistant
- inbox summary
image: assets/store-og.png
image_alt: Morning Brief app preview showing a daily briefing timeline
media:
- type: image
path: assets/screenshots/dashboard.png
alt: Morning Brief dashboard with today's calendar and inbox summary
- type: video
path: assets/demo.mp4
poster: assets/demo-poster.jpg
alt: Morning Brief demo
preview: demo
noindex: falseField rules:
title: optional listing headline used for the page H1 and social title, up to 70 chars. Defaults toname, then a humanized listing id.description: optional store/social summary, up to 180 chars. Defaults to the top-leveldescription.long_description: optional rich store page copy, up to 12,000 chars.categoryorcategories: optional category seeds for first publish.homepageandrepository: optional links shown on the store page.keywords: optional list used for metadata and Rome Store search, up to 12 entries, each up to 50 chars. Duplicate entries are folded case-insensitively.image: optional relative path under.rome_store/to the social card image. Use PNG, JPEG, or WebP; 1200x630 is recommended; max size is 2 MB.image_alt: optional alt text forimage, up to 200 chars.media: optional list of up to 8 images/videos shown on the store page. Images may be PNG, JPEG, or WebP and must be at most 2 MB. Videos may be MP4, WebM, or MOV and must be at most 25 MB. Videoposterpaths must point at images.preview: optional preview link mode.off(the default) hides the preview link,onlinks to Rome Cloud's built-in/preview/<listing>page when the latest bundle has a web UI, anddemolinks tohttps://demo.romeos.cc/full/apps/<appId>.noindex: optional boolean. Usetrueonly for a listing you want published but omitted from search indexes and the sitemap.
Store asset paths must point inside .rome_store/. Absolute URLs, absolute
paths, and .. path traversal are rejected at publish time. Rome Cloud always
derives the canonical listing URL itself; apps cannot set canonical.
The .rome_store directory is a Rome App Store-only sidecar: rome publish uploads
it separately from the app bundle, and installable bundles exclude it so store
screenshots and videos are not sent to user machines.
Listing IDs And Handles
Publishing uses the id in app.yaml as the store listing id. For local
source installs, keep id as the plain app id you run in Rome. For store
publishes, the API also accepts scoped listing ids:
id: "@your-handle/your-app"Watch out: the Rome runtime itself never accepts a scoped id.
app.yaml#idmust match/^[a-z][a-z0-9-]{0,63}$/to build, pack, or install, so the daemon cannot build or install an app whose manifest carries@your-handle/your-app— only the store accepts the scoped form. Keep the plain id inapp.yamlfor local installs; for a scoped publish, editapp.yaml#idin a copy of the packed artifact just beforerome publish.
Use scoped ids when you are publishing directly to a handle-owned namespace. The
first successful publish for an unclaimed handle claims that handle for the
publishing account, with owner role. After that, only authorized publishers
for that handle can publish additional versions. The reserved @rome handle is
for operator-owned first-party apps.
Owners can grant additional teammates the right to publish under the same
handle from Dashboard → My apps → Manage publishers. The grant page lists
every account with access, lets the owner add a teammate by their store
account email (as owner or publisher), and lets the owner revoke access.
The handle's last owner cannot be removed.
Unscoped listing ids such as your-app are also valid, but they claim only that
single unscoped listing namespace. Scoped ids are easier to reason about for
third-party apps because the handle clearly identifies the publisher.
Authenticate
The rome CLI ships with @rome-os/app-web-sdk, which every scaffolded Rome
app already depends on — inside an app directory, rome is on your PATH via
node_modules/.bin. Outside an app, run it ad hoc:
npx -p @rome-os/app-web-sdk rome --helpFor long-lived workflows, generate a token in the store dashboard under Settings -> CLI / API token and export it:
export ROME_TOKEN=<token>
export ROME_STORE_HOST=https://romeos.cc
rome whoamiFor an interactive shell, you can use a 30-day login session instead:
rome login --host https://romeos.cc
rome whoamiROME_TOKEN wins when both authentication methods are present.
Publish
Package a local Rome app into a release artifact, then publish that artifact.
The daemon builds + packs into <app>/.rome/artifact during a source-mode
install:
// system:app_management
{ "op": "install", "source": { "mode": "source", "path": "<absolute app root>" } }APP=~/.rome/<profile>/projects/apps/<appId>
rome publish "$APP/.rome/artifact" --dry-run --out "$APP/.rome/app.romeapp"
rome publish "$APP/.rome/artifact"Use --exclude <name> for any files that should not be included in the upload:
rome publish "$APP/.rome/artifact" --exclude .env --exclude tmpThe CLI excludes node_modules, .git, and .DS_Store from the installable
app bundle by default, and always excludes .rome_store. When
<app>/.rome_store/rome_store.yaml exists, the CLI uploads .rome_store as a
separate store sidecar.
After Publishing
After publish succeeds:
- Open the store dashboard's My apps to see listings you can publish under.
- Open the store dashboard's Store tab or the Rome dashboard App Store to confirm the listing appears.
- Install from the Rome dashboard App Store, or install through the app
lifecycle API with an
appstoresource that names the listing id.versionandcontentHashare optional — when omitted, the daemon resolves the latest live version and its hash from the listing.
For an update, bump app.yaml#version, re-run the source-mode install
(which rebuilds and repacks), and run rome publish again. The listing id
must stay the same.
Common Failures
Not logged in: setROME_TOKENor runrome login --host <url>.Not authorized to publish under handle: publish under a handle you own, ask the owner to add you as a publisher, or choose a new unclaimed handle.Handle is reserved: reserved handles such as@romerequire an operator account.Version is not strictly higher: bumpapp.yaml#versionto a SemVer value greater than the listing's current highest version.Missing app.yaml: pass a Rome app artifact directory, usually the<app>/.rome/artifactdirectory a source-mode install writes.- Missing web/API/action files during install: re-run the
system:app_managementsource-mode install (it rebuilds and repacks), then republish the newly packed artifact.
CLI command details live in the @rome-os/app-web-sdk package README.