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/artifact

Use 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.svg

Required by the store:

  • id
  • version
  • description

Recommended for public listings:

  • name
  • icon
  • .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: false

Field rules:

  • title: optional listing headline used for the page H1 and social title, up to 70 chars. Defaults to name, then a humanized listing id.
  • description: optional store/social summary, up to 180 chars. Defaults to the top-level description.
  • long_description: optional rich store page copy, up to 12,000 chars.
  • category or categories: optional category seeds for first publish.
  • homepage and repository: 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 for image, 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. Video poster paths must point at images.
  • preview: optional preview link mode. off (the default) hides the preview link, on links to Rome Cloud's built-in /preview/<listing> page when the latest bundle has a web UI, and demo links to https://demo.romeos.cc/full/apps/<appId>.
  • noindex: optional boolean. Use true only 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#id must 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 in app.yaml for local installs; for a scoped publish, edit app.yaml#id in a copy of the packed artifact just before rome 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 --help

For 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 whoami

For an interactive shell, you can use a 30-day login session instead:

rome login --host https://romeos.cc
rome whoami

ROME_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 tmp

The 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:

  1. Open the store dashboard's My apps to see listings you can publish under.
  2. Open the store dashboard's Store tab or the Rome dashboard App Store to confirm the listing appears.
  3. Install from the Rome dashboard App Store, or install through the app lifecycle API with an appstore source that names the listing id. version and contentHash are 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: set ROME_TOKEN or run rome 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 @rome require an operator account.
  • Version is not strictly higher: bump app.yaml#version to a SemVer value greater than the listing's current highest version.
  • Missing app.yaml: pass a Rome app artifact directory, usually the <app>/.rome/artifact directory a source-mode install writes.
  • Missing web/API/action files during install: re-run the system:app_management source-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.

On this page