[READ-ONLY] a fast, modern browser for the npm registry

chore: make it easier to get started

+69 -76
+26 -14
README.md
··· 20 20 21 21 ## Features 22 22 23 - - **Dark mode by default** - Easy on the eyes, no toggle needed 24 - - **Package browsing** - Fast search, package details, READMEs, versions, dependencies 25 - - **Dependencies view** - Shows regular dependencies and peer dependencies (with optional badges) 26 - - **User profiles** - View any npm user's public packages at `/~username` 27 - - **Organization pages** - Browse org packages at `/org/orgname` 28 - - **Provenance indicators** - Verified build indicators for packages with npm provenance 29 - - **Admin features** - Org/team management, package access controls via local connector 23 + - **Dark mode by default** - easier on the eyes 24 + - **Package browsing** - fast search, package details, READMEs, versions, dependencies 25 + - **User profiles** - view any npm user's public packages at `/~username` 26 + - **Organization pages** - browse org packages at `/org/orgname` 27 + - **Provenance indicators** - verified build indicators for packages with npm provenance 28 + - **Admin features** - org/team management, package access controls via local connector (coming soon) 30 29 31 30 ### URL Compatibility 32 31 ··· 41 40 | `/~<username>` | [`/~sindresorhus`](https://npmx.dev/~sindresorhus) | 42 41 | `/org/<name>` | [`/org/nuxt`](https://npmx.dev/org/nuxt) | 43 42 44 - **Coming soon** (with local connector): `/package/<name>/access`, `/package/<name>/collaborators`, `/settings/*` 45 - 46 43 ## Tech Stack 47 44 48 - - [Nuxt 4](https://nuxt.com/) - Vue framework 49 - - [Nitro](https://nuxt.com/docs/guide/concepts/server-engine) - Server engine with API routes 50 - - [UnoCSS](https://unocss.dev/) - Atomic CSS engine 51 - - [nuxt-og-image](https://github.com/nuxt-modules/og-image) - Dynamic OG images 52 - - [npm Registry API](https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md) - Package data 45 + - [Nuxt 4](https://nuxt.com/) 46 + - [Nitro](https://nuxt.com/docs/guide/concepts/server-engine) 47 + - [UnoCSS](https://unocss.dev/) 48 + - [nuxt-og-image](https://github.com/nuxt-modules/og-image) 49 + - [npm Registry API](https://github.com/npm/registry/blob/main/docs/REGISTRY-API.md) 53 50 54 51 ## Try it out locally 55 52 ··· 85 82 # type check 86 83 pnpm test:types 87 84 ``` 85 + 86 + ### Local Connector (CLI) 87 + 88 + The `cli/` workspace contains a local connector that enables authenticated npm operations from the web UI. It runs on your machine and uses your existing npm credentials. 89 + 90 + ```bash 91 + # run the connector in dev mode 92 + pnpm --filter @npmx/connector dev 93 + 94 + # or build and run the production version 95 + pnpm --filter @npmx/connector build 96 + node cli/dist/cli.mjs 97 + ``` 98 + 99 + The connector will check your npm authentication, generate a connection token, and listen for requests from npmx.dev. 88 100 89 101 ## License 90 102
+3 -4
cli/package.json
··· 18 18 ], 19 19 "scripts": { 20 20 "build": "unbuild", 21 - "dev": "tsx src/cli.ts", 22 - "typecheck": "tsc --noEmit" 21 + "dev": "node --experimental-strip-types src/cli.ts", 22 + "test:types": "tsc --noEmit" 23 23 }, 24 24 "dependencies": { 25 25 "@clack/prompts": "1.0.0-alpha.9", ··· 32 32 "picocolors": "^1.1.1" 33 33 }, 34 34 "devDependencies": { 35 - "@types/node": "^25.0.10", 36 - "tsx": "^4.21.0", 35 + "@types/node": "^24.10.9", 37 36 "typescript": "^5.9.3", 38 37 "unbuild": "^3.6.1" 39 38 }
+3 -3
cli/src/cli.ts
··· 2 2 import { defineCommand, runMain } from 'citty' 3 3 import { listen } from 'listhen' 4 4 import { toNodeListener } from 'h3' 5 - import { createConnectorApp, generateToken, CONNECTOR_VERSION } from './server' 6 - import { getNpmUser } from './npm-client' 7 - import { initLogger, showToken, logInfo, showAuthRequired } from './logger' 5 + import { createConnectorApp, generateToken, CONNECTOR_VERSION } from './server.ts' 6 + import { getNpmUser } from './npm-client.ts' 7 + import { initLogger, showToken, logInfo, showAuthRequired } from './logger.ts' 8 8 9 9 const DEFAULT_PORT = 31415 10 10
+2 -2
cli/src/index.ts
··· 1 - export * from './types' 2 - export { createConnectorApp, generateToken } from './server' 1 + export * from './types.ts' 2 + export { createConnectorApp, generateToken } from './server.ts'
+1 -1
cli/src/npm-client.ts
··· 1 1 import { exec } from 'node:child_process' 2 2 import { promisify } from 'node:util' 3 - import { logCommand, logSuccess, logError } from './logger' 3 + import { logCommand, logSuccess, logError } from './logger.ts' 4 4 5 5 const execAsync = promisify(exec) 6 6
+2 -2
cli/src/server.ts
··· 8 8 PendingOperation, 9 9 OperationType, 10 10 ApiResponse, 11 - } from './types' 11 + } from './types.ts' 12 12 import { 13 13 getNpmUser, 14 14 orgAddUser, ··· 26 26 ownerAdd, 27 27 ownerRemove, 28 28 type NpmExecResult, 29 - } from './npm-client' 29 + } from './npm-client.ts' 30 30 31 31 // Read version from package.json 32 32 const __dirname = dirname(fileURLToPath(import.meta.url))
+10 -5
cli/tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 3 "target": "ES2022", 4 - "module": "ESNext", 5 - "moduleResolution": "bundler", 4 + "module": "nodenext", 6 5 "strict": true, 7 6 "esModuleInterop": true, 8 7 "skipLibCheck": true, 9 - "outDir": "dist", 8 + "noEmit": true, 9 + "allowImportingTsExtensions": true, 10 10 "declaration": true, 11 11 "declarationMap": true 12 12 }, 13 - "include": ["src/**/*.ts"], 14 - "exclude": ["node_modules", "dist"] 13 + "include": [ 14 + "src/**/*.ts" 15 + ], 16 + "exclude": [ 17 + "node_modules", 18 + "dist" 19 + ] 15 20 }
+22 -45
pnpm-lock.yaml
··· 169 169 version: 1.1.1 170 170 devDependencies: 171 171 '@types/node': 172 - specifier: ^25.0.10 173 - version: 25.0.10 174 - tsx: 175 - specifier: ^4.21.0 176 - version: 4.21.0 172 + specifier: ^24.10.9 173 + version: 24.10.9 177 174 typescript: 178 175 specifier: ^5.9.3 179 176 version: 5.9.3 ··· 1615 1612 resolution: {integrity: sha512-laqfmMcWWNV1FsVmm1+RQUoGY8NIJvCRl0z0K8ikqPukoEry0LXMqlQ+xaf8xJRvoH2/78OhZmsEEsUBTXipcw==} 1616 1613 engines: {node: '>=18.12.0'} 1617 1614 1618 - '@nuxt/kit@4.2.2': 1619 - resolution: {integrity: sha512-ZAgYBrPz/yhVgDznBNdQj2vhmOp31haJbO0I0iah/P9atw+OHH7NJLUZ3PK+LOz/0fblKTN1XJVSi8YQ1TQ0KA==} 1620 - engines: {node: '>=18.12.0'} 1621 - 1622 1615 '@nuxt/kit@4.3.0': 1623 1616 resolution: {integrity: sha512-cD/0UU9RQmlnTbmyJTDyzN8f6CzpziDLv3tFQCnwl0Aoxt3KmFu4k/XA4Sogxqj7jJ/3cdX1kL+Lnsh34sxcQQ==} 1624 1617 engines: {node: '>=18.12.0'} ··· 2613 2606 2614 2607 '@types/mdast@4.0.4': 2615 2608 resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} 2609 + 2610 + '@types/node@24.10.9': 2611 + resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==} 2616 2612 2617 2613 '@types/node@25.0.10': 2618 2614 resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==} ··· 8640 8636 8641 8637 '@nuxt/devtools-kit@3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': 8642 8638 dependencies: 8643 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 8639 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 8644 8640 execa: 8.0.1 8645 8641 vite: 7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) 8646 8642 transitivePeerDependencies: ··· 8744 8740 '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) 8745 8741 '@nuxt/eslint-config': 1.12.1(@typescript-eslint/utils@8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.27)(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) 8746 8742 '@nuxt/eslint-plugin': 1.12.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) 8747 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 8743 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 8748 8744 chokidar: 5.0.0 8749 8745 eslint: 9.39.2(jiti@2.6.1) 8750 8746 eslint-flat-config-utils: 2.1.4 ··· 8769 8765 '@nuxt/fonts@0.13.0(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': 8770 8766 dependencies: 8771 8767 '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) 8772 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 8768 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 8773 8769 consola: 3.4.2 8774 8770 css-tree: 3.1.0 8775 8771 defu: 6.1.4 ··· 8838 8834 transitivePeerDependencies: 8839 8835 - magicast 8840 8836 8841 - '@nuxt/kit@4.2.2(magicast@0.5.1)': 8842 - dependencies: 8843 - c12: 3.3.3(magicast@0.5.1) 8844 - consola: 3.4.2 8845 - defu: 6.1.4 8846 - destr: 2.0.5 8847 - errx: 0.1.0 8848 - exsolve: 1.0.8 8849 - ignore: 7.0.5 8850 - jiti: 2.6.1 8851 - klona: 2.0.6 8852 - mlly: 1.8.0 8853 - ohash: 2.0.11 8854 - pathe: 2.0.3 8855 - pkg-types: 2.3.0 8856 - rc9: 2.1.2 8857 - scule: 1.3.0 8858 - semver: 7.7.3 8859 - tinyglobby: 0.2.15 8860 - ufo: 1.6.3 8861 - unctx: 2.5.0 8862 - untyped: 2.0.0 8863 - transitivePeerDependencies: 8864 - - magicast 8865 - 8866 8837 '@nuxt/kit@4.3.0(magicast@0.5.1)': 8867 8838 dependencies: 8868 8839 c12: 3.3.3(magicast@0.5.1) ··· 8963 8934 8964 8935 '@nuxt/scripts@0.13.2(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))': 8965 8936 dependencies: 8966 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 8937 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 8967 8938 '@unhead/vue': 2.1.2(vue@3.5.27(typescript@5.9.3)) 8968 8939 '@vueuse/core': 14.1.0(vue@3.5.27(typescript@5.9.3)) 8969 8940 consola: 3.4.2 ··· 9788 9759 '@types/mdast@4.0.4': 9789 9760 dependencies: 9790 9761 '@types/unist': 3.0.3 9762 + 9763 + '@types/node@24.10.9': 9764 + dependencies: 9765 + undici-types: 7.16.0 9791 9766 9792 9767 '@types/node@25.0.10': 9793 9768 dependencies: 9794 9769 undici-types: 7.16.0 9770 + optional: true 9795 9771 9796 9772 '@types/parse-path@7.1.0': 9797 9773 dependencies: ··· 9815 9791 9816 9792 '@types/ws@8.18.1': 9817 9793 dependencies: 9818 - '@types/node': 25.0.10 9794 + '@types/node': 24.10.9 9819 9795 9820 9796 '@typescript-eslint/eslint-plugin@8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': 9821 9797 dependencies: ··· 9964 9940 9965 9941 '@unocss/nuxt@66.6.0(magicast@0.5.1)(postcss@8.5.6)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(webpack@5.104.1(esbuild@0.27.2))': 9966 9942 dependencies: 9967 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 9943 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 9968 9944 '@unocss/config': 66.6.0 9969 9945 '@unocss/core': 66.6.0 9970 9946 '@unocss/preset-attributify': 66.6.0 ··· 10880 10856 10881 10857 chrome-launcher@1.2.1: 10882 10858 dependencies: 10883 - '@types/node': 25.0.10 10859 + '@types/node': 24.10.9 10884 10860 escape-string-regexp: 4.0.0 10885 10861 is-wsl: 2.2.0 10886 10862 lighthouse-logger: 2.0.2 ··· 12049 12025 12050 12026 happy-dom@20.3.5: 12051 12027 dependencies: 12052 - '@types/node': 25.0.10 12028 + '@types/node': 24.10.9 12053 12029 '@types/whatwg-mimetype': 3.0.2 12054 12030 '@types/ws': 8.18.1 12055 12031 entities: 4.5.0 ··· 12449 12425 12450 12426 jest-worker@27.5.1: 12451 12427 dependencies: 12452 - '@types/node': 25.0.10 12428 + '@types/node': 24.10.9 12453 12429 merge-stream: 2.0.0 12454 12430 supports-color: 8.1.1 12455 12431 ··· 13039 13015 nuxt-og-image@5.1.13(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(magicast@0.5.1)(unstorage@1.17.4(db0@0.3.4)(ioredis@5.9.2))(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)): 13040 13016 dependencies: 13041 13017 '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) 13042 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 13018 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 13043 13019 '@resvg/resvg-js': 2.6.2 13044 13020 '@resvg/resvg-wasm': 2.6.2 13045 13021 '@unhead/vue': 2.1.2(vue@3.5.27(typescript@5.9.3)) ··· 13089 13065 13090 13066 nuxt-site-config@3.2.18(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)): 13091 13067 dependencies: 13092 - '@nuxt/kit': 4.2.2(magicast@0.5.1) 13068 + '@nuxt/kit': 4.3.0(magicast@0.5.1) 13093 13069 h3: 1.15.5 13094 13070 nuxt-site-config-kit: 3.2.18(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) 13095 13071 pathe: 2.0.3 ··· 14513 14489 get-tsconfig: 4.13.0 14514 14490 optionalDependencies: 14515 14491 fsevents: 2.3.3 14492 + optional: true 14516 14493 14517 14494 type-check@0.4.0: 14518 14495 dependencies: