# Publishing your package (/docs/ship/publishing-packages)



Your integration ships as a versioned npm package to Appbrew's private registry. Publishing is automated in your repo: you choose a version bump, the workflow does the rest. You never publish from your laptop and you never handle a publish token.

## Before you publish [#before-you-publish]

Run through the [pre-handoff checklist](/docs/build/testing): both platforms verified, config states covered, manifest settings documented, README current.

## The release flow [#the-release-flow]

<Steps>
  <Step>
    ### Land your changes [#land-your-changes]

    Merge your work to the repo's main branch through your normal review flow.
  </Step>

  <Step>
    ### Run the Release workflow [#run-the-release-workflow]

    In your repo: **Actions → Release → Run workflow**, choosing a bump: `patch` for fixes, `minor` for new capabilities, `major` for breaking changes to your own API or settings schema.

    Your repo ships one of two supported release flows. Some push the version bump directly, others open a release pull request to merge. Your repo's `RELEASING.md` states which one it uses; the choice changes nothing about the outcome.
  </Step>

  <Step>
    ### The publish happens automatically [#the-publish-happens-automatically]

    The workflow verifies the version, publishes the package to `npm.appbrew.tech` with Appbrew-held credentials, tags the release, and creates a GitHub release. If the version already exists, the publish is refused. Versions are immutable.
  </Step>

  <Step>
    ### Tell Appbrew [#tell-appbrew]

    Notify your Appbrew contact that the new version is up, with a line on what changed. Appbrew bumps the pin in the consuming merchant app(s) and ships it — through a store release when your package [requires a native build](/docs/reference/manifest-schema), otherwise with the next scheduled release.
  </Step>
</Steps>

## How platform releases reach you [#how-platform-releases-reach-you]

The flow runs the other way too: Appbrew periodically releases new lockstep `@gauntlet/*` versions. Your sample app pins one platform version; when Appbrew asks you to validate against a newer one, bump the whole `@gauntlet` set in the sample app ([never mixed](/docs/concepts/package-ecosystem)), reinstall, and re-run your integration's flows. Declare the platform versions your package supports in `peerDependencies` ([Versioning and compatibility](/docs/ship/versioning-and-compat)).
