From 577c10e6eb9e62543807230493d97b39b20aa0d2 Mon Sep 17 00:00:00 2001
From: James Garbutt <43081j@users.noreply.github.com>
Date: Tue, 3 Mar 2026 15:47:12 +0000
Subject: [PATCH 1/8] chore: add a little extra validation (#1894)
---
.../api/registry/badge/[type]/[...pkg].get.ts | 28 +++++++++++++------
shared/schemas/social.ts | 14 +++++++++-
2 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts
index fdc994233c..cbab8ac374 100644
--- a/server/api/registry/badge/[type]/[...pkg].get.ts
+++ b/server/api/registry/badge/[type]/[...pkg].get.ts
@@ -87,6 +87,14 @@ function measureDefaultTextWidth(text: string): number {
return Math.max(MIN_BADGE_TEXT_WIDTH, Math.round(text.length * CHAR_WIDTH) + BADGE_PADDING_X * 2)
}
+function escapeXML(str: string): string {
+ return str
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+}
+
function measureShieldsTextLength(text: string): number {
const measuredWidth = measureTextWidth(text, SHIELDS_FONT_SHORTHAND)
@@ -108,9 +116,11 @@ function renderDefaultBadgeSvg(params: {
const rightWidth = measureDefaultTextWidth(finalValue)
const totalWidth = leftWidth + rightWidth
const height = 20
+ const escapedLabel = escapeXML(finalLabel)
+ const escapedValue = escapeXML(finalValue)
return `
-
`.trim()
diff --git a/shared/schemas/social.ts b/shared/schemas/social.ts
index f0c018e11d..1e3305941b 100644
--- a/shared/schemas/social.ts
+++ b/shared/schemas/social.ts
@@ -13,7 +13,19 @@ export type PackageLikeBody = v.InferOutput
// TODO: add 'avatar'
export const ProfileEditBodySchema = v.object({
displayName: v.pipe(v.string(), v.maxLength(640)),
- website: v.optional(v.union([v.literal(''), v.pipe(v.string(), v.url())])),
+ website: v.optional(
+ v.union([
+ v.literal(''),
+ v.pipe(
+ v.string(),
+ v.url(),
+ v.check(
+ url => url.startsWith('https://') || url.startsWith('http://'),
+ 'Website must use http or https',
+ ),
+ ),
+ ]),
+ ),
description: v.optional(v.pipe(v.string(), v.maxLength(2560))),
})
From 1d5feeeb680d677c3049ac3148e4dd43e06e27a3 Mon Sep 17 00:00:00 2001
From: Daniel Roe
Date: Tue, 3 Mar 2026 15:57:31 +0000
Subject: [PATCH 2/8] fix: handle custom canary environment
---
config/env.ts | 8 +++++---
test/unit/config/env.spec.ts | 17 +++++++++++++++++
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/config/env.ts b/config/env.ts
index cbd852d406..ec7cd7ed16 100644
--- a/config/env.ts
+++ b/config/env.ts
@@ -44,13 +44,15 @@ export const gitBranch = process.env.BRANCH || process.env.VERCEL_GIT_COMMIT_REF
* Whether this is the canary environment (main.npmx.dev).
*
* Detected as any non-PR Vercel deploy from the `main` branch
- * (which may receive `VERCEL_ENV === 'production'` or `'preview'`
- * depending on the project's production branch configuration).
+ * (which may receive `VERCEL_ENV === 'production'`, `'preview'`, or a
+ * custom `'canary'` environment depending on the project configuration).
*
* @see {@link https://vercel.com/docs/environment-variables/system-environment-variables#VERCEL_ENV}
*/
export const isCanary =
- (process.env.VERCEL_ENV === 'production' || process.env.VERCEL_ENV === 'preview') &&
+ (process.env.VERCEL_ENV === 'production' ||
+ process.env.VERCEL_ENV === 'preview' ||
+ process.env.VERCEL_ENV === 'canary') &&
gitBranch === 'main' &&
!isPR
diff --git a/test/unit/config/env.spec.ts b/test/unit/config/env.spec.ts
index 48be8159b8..3d3fb0b4ec 100644
--- a/test/unit/config/env.spec.ts
+++ b/test/unit/config/env.spec.ts
@@ -43,6 +43,14 @@ describe('isCanary', () => {
expect(isCanary).toBe(true)
})
+ it('returns true when VERCEL_ENV is custom "canary" and branch is "main"', async () => {
+ vi.stubEnv('VERCEL_ENV', 'canary')
+ vi.stubEnv('VERCEL_GIT_COMMIT_REF', 'main')
+ const { isCanary } = await import('../../../config/env')
+
+ expect(isCanary).toBe(true)
+ })
+
it('returns false when VERCEL_ENV is "preview", branch is "main", but is a PR', async () => {
vi.stubEnv('VERCEL_ENV', 'preview')
vi.stubEnv('VERCEL_GIT_COMMIT_REF', 'main')
@@ -97,6 +105,15 @@ describe('getEnv', () => {
expect(result.env).toBe('canary')
})
+ it('returns "canary" for custom Vercel "canary" environment on main branch', async () => {
+ vi.stubEnv('VERCEL_ENV', 'canary')
+ vi.stubEnv('VERCEL_GIT_COMMIT_REF', 'main')
+ const { getEnv } = await import('../../../config/env')
+ const result = await getEnv(false)
+
+ expect(result.env).toBe('canary')
+ })
+
it('returns "preview" for Vercel preview PR deploys', async () => {
vi.stubEnv('VERCEL_ENV', 'preview')
vi.stubEnv('VERCEL_GIT_PULL_REQUEST_ID', '123')
From 002099971923e8ba88ecd402a06e3d681a530c9c Mon Sep 17 00:00:00 2001
From: Florian <45694132+flo-bit@users.noreply.github.com>
Date: Tue, 3 Mar 2026 17:08:20 +0100
Subject: [PATCH 3/8] chore: add blento to OSS Partners (#1897)
---
app/assets/logos/oss-partners/blento.svg | 6 ++++++
app/assets/logos/oss-partners/index.ts | 6 ++++++
2 files changed, 12 insertions(+)
create mode 100644 app/assets/logos/oss-partners/blento.svg
diff --git a/app/assets/logos/oss-partners/blento.svg b/app/assets/logos/oss-partners/blento.svg
new file mode 100644
index 0000000000..38b4792e7f
--- /dev/null
+++ b/app/assets/logos/oss-partners/blento.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/app/assets/logos/oss-partners/index.ts b/app/assets/logos/oss-partners/index.ts
index 4f14698d4d..e27f78f6b7 100644
--- a/app/assets/logos/oss-partners/index.ts
+++ b/app/assets/logos/oss-partners/index.ts
@@ -30,6 +30,7 @@ import LogoLunaria from './lunaria.svg'
import LogoJsr from './jsr.svg'
import LogoIconify from './iconify.svg'
import LogoFloatingUi from './floating-ui-vue.svg'
+import LogoBlento from './blento.svg'
// The list is used on the about page. To add, simply upload the logos nearby and add an entry here. Prefer SVGs.
// For logo src, specify a string or object with the light and dark theme variants.
@@ -195,4 +196,9 @@ export const OSS_PARTNERS = [
logo: LogoFloatingUi,
url: 'https://floating-ui.com/',
},
+ {
+ name: 'blento',
+ logo: LogoBlento,
+ url: 'https://blento.app/npmx.dev',
+ },
]
From 75255f17103e249654cfa718e5b502dd4be70001 Mon Sep 17 00:00:00 2001
From: Bailey Townsend
Date: Tue, 3 Mar 2026 11:20:14 -0600
Subject: [PATCH 4/8] fix: standard.site fixes (#1901)
---
app/components/global/BlogPostWrapper.vue | 10 ++++
modules/standard-site-sync.ts | 46 ++++++-------------
nuxt.config.ts | 1 +
package.json | 2 +-
pnpm-lock.yaml | 35 ++++++++++++--
.../site.standard.publication.get.ts | 6 +++
server/utils/atproto/utils/likes.ts | 6 +--
shared/utils/atproto.ts | 31 +++++++++++++
shared/utils/constants.ts | 2 +
.../unit/server/utils/likes-evolution.spec.ts | 4 +-
10 files changed, 102 insertions(+), 41 deletions(-)
create mode 100644 server/routes/.well-known/site.standard.publication.get.ts
create mode 100644 shared/utils/atproto.ts
diff --git a/app/components/global/BlogPostWrapper.vue b/app/components/global/BlogPostWrapper.vue
index b2651f0845..d50ad9b8dc 100644
--- a/app/components/global/BlogPostWrapper.vue
+++ b/app/components/global/BlogPostWrapper.vue
@@ -1,5 +1,6 @@