| 1 | --- |
| 2 | title: npm |
| 3 | description: Publish and install a workspace's npm packages on g1t.sh, from your machine and from workflows with G1T_TOKEN. |
| 4 | --- |
| 5 | |
| 6 | g1t.sh is an npm registry for packages scoped by workspace: `@acme/ui` is |
| 7 | the `ui` package of the `acme` workspace. `npm` (and any client that reads |
| 8 | `.npmrc`) publishes and installs them with two lines of configuration. |
| 9 | |
| 10 | ```text |
| 11 | https://g1t.sh/-/npm/ |
| 12 | ``` |
| 13 | |
| 14 | Packages of other scopes and unscoped ones still come from the registry |
| 15 | npm uses by default; only your workspace's scope is pointed at g1t. |
| 16 | |
| 17 | ## Set up `.npmrc` |
| 18 | |
| 19 | In the project (or in `~/.npmrc` for every project), name g1t as the |
| 20 | registry for the workspace's scope, and give it an |
| 21 | [access token](https://g1t.sh/settings/tokens): |
| 22 | |
| 23 | ```ini |
| 24 | @acme:registry=https://g1t.sh/-/npm/ |
| 25 | //g1t.sh/-/npm/:_authToken=${G1T_TOKEN} |
| 26 | ``` |
| 27 | |
| 28 | npm reads `${G1T_TOKEN}` from the environment, so the token itself stays |
| 29 | out of the file you commit. A token with full access works; one with scopes |
| 30 | needs `packages:read` to install private packages and `packages:write` to |
| 31 | publish. Public packages install without a token. |
| 32 | |
| 33 | Check it: |
| 34 | |
| 35 | ```sh |
| 36 | npm whoami --registry https://g1t.sh/-/npm/ |
| 37 | ``` |
| 38 | |
| 39 | `npm login --scope=@acme --auth-type=legacy` also works, with your username |
| 40 | and a g1t token (not your password) as the password. |
| 41 | |
| 42 | ## Publish |
| 43 | |
| 44 | The package's `name` is scoped by its workspace: |
| 45 | |
| 46 | ```json |
| 47 | { |
| 48 | "name": "@acme/ui", |
| 49 | "version": "1.0.0", |
| 50 | "repository": "https://g1t.sh/acme/ui" |
| 51 | } |
| 52 | ``` |
| 53 | |
| 54 | ```sh |
| 55 | npm publish |
| 56 | ``` |
| 57 | |
| 58 | The first publish makes the package. When its `repository` is a g1t.sh |
| 59 | repository of the same workspace, or a repository is named like the |
| 60 | package, it is linked to that repository and has its visibility and roles: |
| 61 | publishing needs Write on it. Otherwise it is the workspace's, private, |
| 62 | and needs the workspace's Write base permission. See |
| 63 | [who can see and publish a package](/guides/packages/#who-can-see-and-publish-a-package). |
| 64 | |
| 65 | A version is published once: publishing a version that is already there is |
| 66 | refused, so bump `version` first. `npm publish --tag next` publishes |
| 67 | without moving `latest`. The README of the version `latest` points to is |
| 68 | shown on the package's page. |
| 69 | |
| 70 | ## Install |
| 71 | |
| 72 | ```sh |
| 73 | npm install @acme/ui |
| 74 | ``` |
| 75 | |
| 76 | Lockfiles record `https://g1t.sh/-/npm/…` tarball addresses and each |
| 77 | tarball's `sha512` integrity, which g1t computes when the version is |
| 78 | published. |
| 79 | |
| 80 | ## In workflows |
| 81 | |
| 82 | A workflow's `G1T_TOKEN` is the workspace's own token for the run, and can |
| 83 | install and publish the workspace's packages: |
| 84 | |
| 85 | ```yaml |
| 86 | jobs: |
| 87 | publish: |
| 88 | runs-on: ubuntu-latest |
| 89 | steps: |
| 90 | - uses: actions/checkout@v4 |
| 91 | - uses: actions/setup-node@v4 |
| 92 | with: |
| 93 | node-version: 22 |
| 94 | - run: | |
| 95 | echo "@acme:registry=https://g1t.sh/-/npm/" >> .npmrc |
| 96 | echo "//g1t.sh/-/npm/:_authToken=\${G1T_TOKEN}" >> .npmrc |
| 97 | - run: npm ci |
| 98 | - run: npm publish |
| 99 | env: |
| 100 | G1T_TOKEN: ${{ secrets.G1T_TOKEN }} |
| 101 | ``` |
| 102 | |
| 103 | `npm ci` needs the token too when the project depends on private packages; |
| 104 | set `G1T_TOKEN` for the whole job instead. |
| 105 | |
| 106 | ## Tags, deprecating and unpublishing |
| 107 | |
| 108 | ```sh |
| 109 | npm dist-tag add @acme/ui@1.2.0 stable |
| 110 | npm dist-tag ls @acme/ui |
| 111 | npm deprecate @acme/ui@1.0.0 "Use 1.2 or later" |
| 112 | npm unpublish @acme/ui@1.2.1 |
| 113 | npm unpublish @acme/ui --force |
| 114 | ``` |
| 115 | |
| 116 | Moving tags and deprecating need what publishing does. Unpublishing a |
| 117 | version needs it too within 72 hours of publishing; after that it needs |
| 118 | Admin on the linked repository (an owner, for the workspace's own |
| 119 | packages). Deprecate a version instead when people may depend on it. |
| 120 | Versions can also be deleted on the package's page. |
| 121 | |
| 122 | ## Size |
| 123 | |
| 124 | A publish is one request with the tarball inside it, and may hold at most |
| 125 | 100 MB. Without the [g1t plan](/guides/usage-and-billing/#the-g1t-plan), a |
| 126 | workspace's private packages may hold 500 MB and its public ones 10 GB, as |
| 127 | for [container images](/guides/containers/#storage-and-pull-limits). |
| 128 | |
| 129 | ## Errors |
| 130 | |
| 131 | | Error | Means | |
| 132 | | --- | --- | |
| 133 | | `E401` | No token, or a wrong or expired one. Check `.npmrc` and `npm whoami`. | |
| 134 | | `E403` | Signed in, but your role or your token's scopes do not allow it, or the version is already published. The message says which. | |
| 135 | | `E404` | No such package, or one you cannot see. A private package needs a token in `.npmrc`. | |
| 136 | | `E413` | The publish is over 100 MB. Leave build output and fixtures out with `files` in `package.json` or `.npmignore`. | |