cloudflare / cloudflare/vinext
Metadata: og:image / twitter:image URLs are not percent-encoded
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 120
Description
### What happened
vinext emits `og:image` / `twitter:image` URLs without percent-encoding, where Next.js encodes them. A URL containing a space is passed through verbatim.
```
Next.js 16.3.2
https://file.devfive.kr/file/2025_06_10/1749539238715_1732690349249_1728972833495_image%2016.webp
vinext
https://file.devfive.kr/file/2025_06_10/1749539238715_1732690349249_1728972833495_image 16.webp
```
Note `image%2016.webp` vs `image 16.webp`.
### Reproduction
Return a metadata image whose URL contains a character that must be percent-encoded:
```ts
export async function generateMetadata(): Promise {
return {
openGraph: {
images: ['https://example.com/path/my image.webp'],
},
}
}
```
- Next.js renders `content="https://example.com/path/my%20image.webp"`.
- vinext renders `content="https://example.com/path/my image.webp"`.
In our case the URL comes from a CMS field, so we do not control whether it contains spaces.
### Impact
A raw space inside a `content` URL is not a valid URI. Crawlers and preview generators (Open Graph consumers, chat clients) may fail to fetch the image, so link previews can silently break. Affected 2 of 25 captured URLs in our app — only those whose CMS image name contains a space.
### Expected
Match Next.js and normalize metadata image URLs (e.g. via `new URL(...).href` or equivalent encoding) before writing them into `og:image` / `twitter:image`.
### Environment
- vinext 1.0.0-beta.8, Vite 8.2.2
- Next.js 16.3.2 API surface, App Router, `generateMetadata`
- `--platform=node`, `output: 'standalone'`
Found by a golden-master diff of SSR HTML between the two runtimes on the same source and same API fixtures.
Contributor guide
Research direction
Start at the metadata handling used by generateMetadata, focusing on how openGraph.images values become og:image and twitter:image content attributes. Reproduce the example with a space in the image URL, then verify the rendered URLs use percent-encoding and match the Next.js output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100