---
title: "Publishing Widgets"
description: "Publish your GlassHome widgets to Hub. Login, validate, version, select scope, and publish."
canonical: https://glasshome.app/docs/widget-publishing
section: "CLI & Publishing"
updated: 2026-06-09
---
# Publishing Widgets

Share your widgets with the GlassHome community by publishing them to Hub.

## Publish Flow

```d2
direction: down

cli: Widget CLI: login · validate · publish
hub: GlassHome Hub: gate checks, then published
dash: Dashboards: installable in one click

cli -> hub: build + upload
hub -> dash: live immediately, no review queue
```

  1. You only need to run this explicitly if you want to authenticate before publishing. The `publish` command auto-runs login if no token is found, so this step is optional in practice.
   
       ```bash
       bun widget login
       ```
   
       This runs an OAuth PKCE flow against Hub. A browser opens; the callback lands on `http://127.0.0.1:9274/callback`. The resulting token is stored locally and reused on subsequent publishes. This is separate from `bun widget connect`, which authenticates against your local Dash instance using a device-code flow.
  2. Checks manifests, bundle sizes, and SDK version compatibility. Fix any issues before publishing.
   
       ```bash
       bun widget validate
       ```
  3. The CLI validates first, then prompts you to select which widget to publish, choose a scope, and pick a version bump. It then builds and uploads the bundle to Hub via a presigned R2 URL.
   
       ```bash
       bun widget publish
       ```
   
       Use flags to skip prompts:
   
       - `--name <widget>`: publish only the named widget.
       - `--bump keep|patch|minor|major`: pre-pick the version bump. This updates the `version` field in `src/<name>/manifest.json`.
       - `--scope <scope>`: pre-pick the publishing scope.

## Publish lifecycle

The gate checks in the diagram above are enforced server-side, with precise failures:

- **Bundle > 2 MB** → rejected with `400`.
- **Duplicate version** → `409`; published versions are immutable.
- **Scope you don't own** → rejected. Org scopes require the `owner` or `admin` role.

## Versioning

The `version` field lives in `src/<name>/manifest.json`. The `--bump` flag increments it automatically. Versions follow semver:

- **Patch (0.1.0 → 0.1.1).** Bug fixes, no config changes.
- **Minor (0.1.0 → 0.2.0).** New features, backward-compatible config.
- **Major (0.2.0 → 1.0.0).** Breaking config changes (bump `configVersion` too and add a `migrate` function; see [Config Migrations](/docs/widget-migrations)).

> **On SDK 1.0:** Widgets must target `@glasshome/widget-sdk` 1.x and declare a `capabilities` block, or publish is rejected. See [Upgrading to SDK 1.0](/docs/widget-sdk-1-0).

## Publishing Scopes

When you publish, the CLI prompts you to select a publishing scope if you belong to any organizations:

```
? Select publishing scope:
  ❯ @your-username (personal)
    @my-team (organization)
```

Personal scope uses your username. Organization scope uses the org slug. You can create organizations on [GlassHome Hub](/docs/organizations).

## Yank, deprecation, and release notes

The database schema tracks `yanked`, `yankedReason`, `deprecationMessage`, and `releaseNotes` per version. There is no user-facing mechanism to yank or deprecate a version yourself yet. If you publish a broken version and need it pulled, contact me directly and I'll yank it.

`releaseNotes` will be shown in the widget detail view once that UI is built.

## After Publishing

Your widget appears in the Widget Browser, installable in one click. To ship an update, bump the version and run `publish` again.

## Trust Badges

- **Official.** Maintained by GlassHome. Installed without a confirmation dialog.
- **Community.** Published by users. Users see a consent dialog before installing.

> **Bundle size:** Keep your widget bundles small. The hard limit is 2 MB (rejected at publish time). The CLI shows bundle sizes during `validate` and `info`. Large bundles slow down dashboard loading for everyone.