Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
02ad831
fix(i18n): add missing pt-BR translations for "shortcuts" (#2532)
tcelestino Apr 15, 2026
0ca1692
fix: set default smoothing to 0 (#2535)
graphieros Apr 15, 2026
5fc9e99
fix(i18n): format compare sparkline data labels (#2537)
graphieros Apr 15, 2026
609a391
chore(i18n): fix lunaria pre-commit hook with force: true (#2528)
romansp Apr 15, 2026
32bf8bb
feat: add timeline tab to package page (#2245)
43081j Apr 15, 2026
75bce20
chore: add issue types and missing label to issue templates (#2544)
mootari Apr 15, 2026
c441377
fix(i18n): add missing translations to Brazilian Portuguese (#2542)
tcelestino Apr 16, 2026
6db03a6
feat(i18n): update French translations (#2547)
Limerio Apr 16, 2026
ca5e399
fix: use fast-npm-meta in timeline (#2546)
43081j Apr 16, 2026
b541ee2
docs(ui): add stories for Settings page (#2545)
cylewaitforit Apr 16, 2026
da0897b
fix: show integers for values below 1k in trends chart tooltip (#2550)
graphieros Apr 16, 2026
791ce70
fix: resolve readme copy functionality in Safari (#2554)
MatteoGabriele Apr 17, 2026
b9c3a1d
feat: new og images (#2292)
harlan-zw Apr 17, 2026
cbcdc54
fix: avoid showing "No README is available" during README load (#2473)
akadotsh Apr 17, 2026
b7f71a6
fix: round chart numbers in `applyDataCorrection` for consistent roun…
ulrichstark Apr 18, 2026
ca5c9b4
fix(i18n): update French localizations (#2560)
WarningImHack3r Apr 18, 2026
d9f8d56
feat: add stale workflow (#2555)
MatteoGabriele Apr 18, 2026
e365dd4
chore: increase operation per run in stale workflow (#2564)
MatteoGabriele Apr 18, 2026
5f30d25
chore: remove stale bot (#2566)
MatteoGabriele Apr 18, 2026
400ddf8
feat(i18n): update hi-IN and mr-IN translation for npmx tagline (#2567)
trivikr Apr 19, 2026
5cfe58f
chore: add workflow for stale prs and issue type bug (#2580)
MatteoGabriele Apr 19, 2026
aaaec6a
chore(deps): update dependency nuxt to v4.4.2 (#2047)
renovate[bot] Apr 19, 2026
4e7eb1d
chore(deps): update nuxt core (#2585)
renovate[bot] Apr 19, 2026
fecb36c
chore: clean up `.env.example` comment formatting + empty values (#2581)
iiio2 Apr 20, 2026
213462e
feat: version history page display download count (#2178)
btea Apr 20, 2026
d8aae4b
fix: filter out security holding packages from Algolia results (#2026)
shuuji3 Apr 20, 2026
2b89cee
chore(deps): lock file maintenance (#2592)
renovate[bot] Apr 20, 2026
13ac6c2
fix(i18n): update language switch immediately without refresh (#2525)
BittuBarnwal7479 Apr 20, 2026
67b1322
ci: disable e18e action duplicate dep PR comments (#2593)
serhalp Apr 20, 2026
6e9a66a
chore: remove storybook directory from chromatic externals (#2598)
cylewaitforit Apr 20, 2026
94ef76d
fix(ui): add loading state for translation status generated time (#2589)
cylewaitforit Apr 20, 2026
2dcc3de
fix: download correct variant and fix layout shift on brand page (#2…
Adebesin-Cell Apr 20, 2026
076dde1
perf: prevent duplicates in file tree sprite (#2586)
ghostdevv Apr 20, 2026
5131302
docs(ui): move non-config files out of .storybook directory (#2597)
cylewaitforit Apr 20, 2026
8117059
fix(ui): inline headings inside collapsible summaries (#2599)
Adebesin-Cell Apr 20, 2026
8b5edf2
docs(ui): add stories for Translation Status page (#2559)
cylewaitforit Apr 20, 2026
d12559c
docs(ui): add stories for Error page (#2601)
cylewaitforit Apr 20, 2026
189a568
chore(deps): update dependency @nuxt/scripts to v1 (#2591)
renovate[bot] Apr 20, 2026
de26d13
fix(ui): bail on fetchMore recursion when no new items (#2606)
jonchurch Apr 21, 2026
4565f23
fix(i18n): add missing Russian translations (#2607)
dragomano Apr 21, 2026
c8fcd11
feat: module replacements v3 (#2068)
gameroman Apr 21, 2026
54711c9
fix: improve packages UI (#2530)
abhi123vj Apr 22, 2026
8372d67
refactor(ui): redesign footer with sectioned columns, logo, and socia…
j0u1 Apr 22, 2026
3c3bfeb
fix: adjust logo sizing on about page (#1986)
vladh Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#secure password, can use openssl rand -hex 32
# secure password, can use `openssl rand -hex 32`
NUXT_SESSION_PASSWORD=""

#HMAC secret for image proxy URL signing, can use openssl rand -hex 32
NUXT_IMAGE_PROXY_SECRET=""
# HMAC secret for image-proxy and OG image URL signing, can use `openssl rand -hex 32`
NUXT_IMAGE_PROXY_SECRET=""
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: "\U0001F41E Bug report"
description: Create a report to help us improve npmx
type: bug
labels: ['pending triage']
body:
- type: markdown
attributes:
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature-request.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: '🚀 Feature request'
description: Suggest a feature that will improve npmx
type: feature
labels: ['pending triage']
body:
- type: markdown
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: 👑 Fix Git ownership
run: git config --global --add safe.directory /__w/npmx.dev/npmx.dev

- uses: voidzero-dev/setup-vp@8ecb39174989ce55af90f45cf55b02738599831d # v1
with:
node-version: lts/*
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/dependency-diff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ jobs:
with:
mode: artifact
detect-replacements: 'true'
duplicate-threshold: '4'
# Too noisy. Disabling until this can report on duplicate CHANGES in this PR.
duplicate-threshold: '999'
dependency-threshold: '15'
size-threshold: '200000'

Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Stale Issues and PRs

on:
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch: # Allow manual trigger

permissions:
issues: write
pull-requests: write

jobs:
stale-bugs:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f
with:
days-before-issue-stale: 30
days-before-issue-close: 7
days-before-pr-stale: -1
days-before-pr-close: -1
remove-stale-when-updated: true
only-issue-types: 'bug'
stale-issue-label: 'stale'
close-issue-label: 'stale'
operations-per-run: 500

stale-prs:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f
with:
days-before-issue-stale: -1
days-before-issue-close: -1
days-before-pr-stale: 30
days-before-pr-close: 7
remove-stale-when-updated: true
stale-pr-label: 'stale'
close-pr-label: 'stale'
operations-per-run: 500
2 changes: 1 addition & 1 deletion .nuxtrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
setups.@nuxt/test-utils="4.0.0"
setups.@nuxt/test-utils="4.0.2"
3 changes: 1 addition & 2 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { resolve } from 'node:path'
const config = {
stories: [
// List welcome first in sidebar
'../.storybook/docs/welcome.mdx',
'../.storybook/docs/*.mdx',
'../app/storybook/welcome.mdx',
'../app/**/*.@(mdx|stories.@(js|ts))',
],
addons: [
Expand Down
16 changes: 16 additions & 0 deletions .storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,19 @@
background-color: var(--bg, oklch(0.171 0 0)) !important;
}
</style>
<script>
// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
// Stub Nuxt specific globals
// @nuxtjs/color-mode's plugin.client.js reads window[globalName] at module
// evaluation time — before any Storybook setup() callback runs — so the
// global must exist in the HTML head, not in preview.ts.
window.__NUXT_COLOR_MODE__ ??= {
preference: 'system',
value: 'dark',
getColorScheme: function () {
return 'dark'
},
addColorScheme: function () {},
removeColorScheme: function () {},
}
</script>
12 changes: 1 addition & 11 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,8 @@ import npmxDark from './theme'

initialize()

// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
// Stub Nuxt specific globals
// @ts-expect-error - dynamic global name
globalThis['__NUXT_COLOR_MODE__'] ??= {
preference: 'system',
value: 'dark',
getColorScheme: fn(() => 'dark'),
addColorScheme: fn(),
removeColorScheme: fn(),
}
// @ts-expect-error - dynamic global name
globalThis.defineOgImageComponent = fn()
globalThis.defineOgImage = fn()

// Subscribe to locale changes from storybook-i18n addon (once, outside decorator)
let currentI18nInstance: any = null
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Ideally, extract utilities into separate files so they can be unit tested. 🙏

### Internal linking

Always use **object syntax with named routes** for internal navigation. This makes links resilient to URL structure changes and provides type safety via `unplugin-vue-router`.
Always use **object syntax with named routes** for internal navigation. This makes links resilient to URL structure changes and provides type safety with the [typedPages Nuxt option](https://nuxt.com/docs/4.x/guide/going-further/experimental-features#typedpages).

```vue
<!-- Good: named route -->
Expand Down
4 changes: 4 additions & 0 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ if (import.meta.client) {
useEventListener(document, 'click', handleModalLightDismiss)
}
}

// title and description will be inferred
// this will be overridden by upstream pages that use different templates
defineOgImage('Page.takumi', {}, { alt: 'npmx — a fast, modern browser for the npm registry' })
</script>

<template>
Expand Down
2 changes: 1 addition & 1 deletion app/assets/logos/sponsors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const SPONSORS = [
dark: LogoNetlify,
light: LogoNetlifyLight,
},
normalisingIndent: '0.125rem',
normalisingIndent: '0.25rem',
url: 'https://netlify.com/',
},
{
Expand Down
14 changes: 10 additions & 4 deletions app/components/About/LogoImg.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ const props = defineProps<{
</script>
<template>
<div v-if="typeof src === 'string'" class="h-full">
<img :src="src" loading="lazy" height="36" class="w-auto block h-full" :alt="alt" />
<img
:src="src"
loading="lazy"
height="36"
class="h-full w-full object-contain block"
:alt="alt"
/>
</div>
<div v-else-if="src.light === 'auto'" class="h-full">
<img
:src="src.dark"
loading="lazy"
height="36"
class="w-auto block light:invert light:grayscale h-full"
class="h-full w-full object-contain block light:invert light:grayscale"
:alt="alt"
/>
</div>
Expand All @@ -27,14 +33,14 @@ const props = defineProps<{
:src="src.dark"
loading="lazy"
height="36"
class="w-auto block light:hidden h-full"
class="h-full w-full object-contain block light:hidden"
:alt="alt"
/>
<img
:src="src.light"
loading="lazy"
height="36"
class="w-auto block hidden light:block h-full"
class="h-full w-full object-contain block hidden light:block"
:alt="alt"
/>
</div>
Expand Down
23 changes: 17 additions & 6 deletions app/components/About/LogoList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,50 @@ const props = defineProps<{
</script>

<template>
<ul class="flex flex-wrap gap-4 md:gap-x-6 md:gap-y-4 list-none">
<li v-for="item in list" :key="item.name">
<ul class="list-none">
<li
v-for="item in list"
:key="item.name"
:style="
'items' in item && `grid-column: span ${item.items.length} / span ${item.items.length};`
"
>
<a
v-if="'logo' in item"
:href="item.url"
target="_blank"
rel="noopener noreferrer"
class="relative flex items-center justify-center h-14 min-w-14 rounded-md hover:bg-fg/10 transition-colors p-1"
class="relative flex items-center justify-center h-16 rounded-md bg-bg-muted hover:bg-bg-subtle border border-border transition-colors py-1 px-3"
:style="{ paddingBlock: item.normalisingIndent }"
:aria-label="item.name"
>
<AboutLogoImg :src="item.logo" :alt="item.name" />
</a>
<div v-else-if="item.items" class="relative flex items-center justify-center">
<div
v-else-if="item.items"
class="relative flex items-center justify-center h-full bg-bg-muted border border-border rounded-md py-1 px-2"
>
<svg
width="11"
height="38"
viewBox="0 0 11 38"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
class="h-full w-auto"
>
<path
d="M5.62151 0C-1.8519 10.6931 -1.89574 27.2683 5.62151 37.9997H10.6709C3.15538 27.2683 3.19922 10.6931 10.6709 0H5.62151Z"
fill="currentColor"
/>
</svg>
<ul class="flex items-center justify-center h-full gap-0.5 list-none">
<li v-for="groupItem in item.items" :key="groupItem.name">
<li v-for="groupItem in item.items" :key="groupItem.name" class="h-full">
<a
:href="groupItem.url"
target="_blank"
rel="noopener noreferrer"
class="relative flex items-center justify-center h-10 min-w-10 rounded-md hover:bg-fg/10 transition-colors p-0.5"
class="relative flex items-center justify-center h-full aspect-square rounded-md hover:bg-bg-subtle border border-transparent hover:border-border transition-colors p-1.5"
:style="{ paddingBlock: groupItem.normalisingIndent }"
:aria-label="groupItem.name"
>
Expand All @@ -70,6 +80,7 @@ const props = defineProps<{
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
class="h-full w-auto"
>
<path
d="M5.04935 0H0C7.4734 10.6931 7.51725 27.2683 0 37.9997H5.04935C12.5648 27.2683 12.521 10.6931 5.04935 0Z"
Expand Down
Loading
Loading