Skip to content

feat(picsum): add Lorem Picsum placeholder image provider#2106

Merged
danielroe merged 5 commits into
nuxt:mainfrom
wotan-allfather:feat/picsum-provider
Feb 7, 2026
Merged

feat(picsum): add Lorem Picsum placeholder image provider#2106
danielroe merged 5 commits into
nuxt:mainfrom
wotan-allfather:feat/picsum-provider

Conversation

@wotan-allfather
Copy link
Copy Markdown
Contributor

Add support for Lorem Picsum (https://picsum.photos/) as a built-in provider for placeholder images during development.

Features:

  • Support for random images with dimensions: /200/300
  • Support for specific images by ID: /id/237/200/300
  • Support for seeded images: /seed/picsum/200/300
  • Modifiers: grayscale, blur (1-10)

Usage:

<NuxtImg provider="picsum" src="id/237" width="200" height="300" />
<NuxtImg provider="picsum" src="id/237" :modifiers="{ grayscale: true, blur: 2 }" width="200" height="300" />

Closes #361

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Add support for Lorem Picsum (https://picsum.photos/) as a built-in provider
for placeholder images during development.

Features:
- Support for random images with dimensions: /200/300
- Support for specific images by ID: /id/237/200/300
- Support for seeded images: /seed/picsum/200/300
- Modifiers: grayscale, blur (1-10)

Usage:
```vue
<NuxtImg provider="picsum" src="id/237" width="200" height="300" />
<NuxtImg provider="picsum" src="id/237" :modifiers="{ grayscale: true, blur: 2 }" width="200" height="300" />
```

Closes nuxt#361
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a new Picsum image provider for the Nuxt Image module. The implementation adds a provider module (src/runtime/providers/picsum.ts) that builds Picsum URLs with optional src, width, height, and modifiers (grayscale, blur), registers the provider in BuiltInProviders (src/provider.ts), enables it in playground config (playground/nuxt.config.ts and playground/app/providers.ts), and adds tests, snapshots, and documentation pages for the new provider.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description is clearly related to the changeset, providing usage examples and feature details for the Picsum provider implementation.
Linked Issues check ✅ Passed The implementation fully addresses #361's requirements: supports ID-based images, seeded images, random images, grayscale and blur modifiers, and comprehensive documentation and tests.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the Picsum provider: provider registration, configuration, implementation, documentation, and tests. No out-of-scope changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The pull request title accurately describes the main change: adding Lorem Picsum as a built-in placeholder image provider. It is concise, specific, and clearly conveys the primary purpose of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/runtime/providers/picsum.ts`:
- Around line 41-47: The Picsum URL builder currently appends only a single
segment when height is provided but width is missing, causing Picsum to
interpret it as a square and ignore the user's intent; update the logic in the
function that builds the parts array (referencing parts, width, height in
src/runtime/providers/picsum.ts) so that if height is provided and width is not
you append two segments (e.g., use height for both width and height) or
otherwise supply a sensible default width before pushing the height segment;
ensure both path segments are always present when either dimension is supplied
so the generated Picsum URL is unambiguous.
- Around line 34-38: The code currently pushes `${type}/${id}` even when id is
undefined (e.g., src === "id"), producing "id/undefined"; update the conditional
around the split result to ensure id is present and non-empty before pushing
into parts — for example change the check that uses src/type/id to require id
(e.g., if (type && (type === 'id' || type === 'seed') && typeof id === 'string'
&& id.trim().length > 0) { parts.push(`${type}/${id}`) }) so you only append
valid id segments and avoid "undefined" in URLs.

In `@test/providers.ts`:
- Line 119: The picsum placeholder currently uses the URL
'https://picsum.photos/200' which Picsum treats as a square (200×200) when only
height is intended; update the picsum provider so that when only height is
specified it emits an explicit height/width path (e.g.
'https://picsum.photos/200/200') or adjust the URL generation logic in the
picsum provider to compose `${height}/${height}` when width is undefined; locate
the picsum entry (symbol: picsum) in test/providers.ts and change its url
generation to produce the explicit 'height/height' form or add a note
documenting the limitation if you prefer not to change the URL.
🧹 Nitpick comments (1)
test/nuxt/providers.test.ts (1)

466-474: Test coverage gap: no tests for src (id/seed) or picsum-specific modifiers (grayscale, blur).

The current test only validates dimension-based URL generation with an empty src. The provider's distinguishing features — id/{id}, seed/{seed}, grayscale, and blur — are untested. Consider adding dedicated test cases similar to how other providers have provider-specific tests (e.g., cloudinary fetch, imageengine modifiers).

Example cases to cover:

  • src = 'id/237' with width: 200, height: 300https://picsum.photos/id/237/200/300
  • src = 'seed/picsum' with width: 200https://picsum.photos/seed/picsum/200
  • Modifiers: { grayscale: true, blur: 5 }?grayscale&blur=5
  • Edge cases: blur: 0, blur: 15 (clamping), src: 'id' (missing ID)

Do you want me to generate the additional test cases?

Comment on lines +34 to +38
if (src && src !== '/') {
const [type, id] = (src.startsWith('/') ? src.slice(1) : src).split('/')
if (type && (type === 'id' || type === 'seed')) {
parts.push(`${type}/${id}`)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing validation: id can be undefined when src is "id" or "seed".

If src is "id" (without a trailing ID value), split('/') yields ["id"], so id is undefined, and parts.push(\${type}/${id}`)produces"id/undefined"` in the URL.

Proposed fix
     if (src && src !== '/') {
       const [type, id] = (src.startsWith('/') ? src.slice(1) : src).split('/')
-      if (type && (type === 'id' || type === 'seed')) {
+      if (type && id && (type === 'id' || type === 'seed')) {
         parts.push(`${type}/${id}`)
       }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (src && src !== '/') {
const [type, id] = (src.startsWith('/') ? src.slice(1) : src).split('/')
if (type && (type === 'id' || type === 'seed')) {
parts.push(`${type}/${id}`)
}
if (src && src !== '/') {
const [type, id] = (src.startsWith('/') ? src.slice(1) : src).split('/')
if (type && id && (type === 'id' || type === 'seed')) {
parts.push(`${type}/${id}`)
}
}
🤖 Prompt for AI Agents
In `@src/runtime/providers/picsum.ts` around lines 34 - 38, The code currently
pushes `${type}/${id}` even when id is undefined (e.g., src === "id"), producing
"id/undefined"; update the conditional around the split result to ensure id is
present and non-empty before pushing into parts — for example change the check
that uses src/type/id to require id (e.g., if (type && (type === 'id' || type
=== 'seed') && typeof id === 'string' && id.trim().length > 0) {
parts.push(`${type}/${id}`) }) so you only append valid id segments and avoid
"undefined" in URLs.

Comment on lines +41 to +47
// Add dimensions - these come after the ID/seed path
if (width) {
parts.push(String(width))
}
if (height) {
parts.push(String(height))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Height without width produces an ambiguous Picsum URL.

When only height is provided, only one path segment is appended (e.g., /200), which Picsum treats as a square image (width = height = 200). This silently ignores the user's intent of specifying only the height dimension.

Consider either: (a) documenting this as a known limitation, or (b) emitting both segments (e.g., using a default width or swapping to /{height}/{height}).

🤖 Prompt for AI Agents
In `@src/runtime/providers/picsum.ts` around lines 41 - 47, The Picsum URL builder
currently appends only a single segment when height is provided but width is
missing, causing Picsum to interpret it as a square and ignore the user's
intent; update the logic in the function that builds the parts array
(referencing parts, width, height in src/runtime/providers/picsum.ts) so that if
height is provided and width is not you append two segments (e.g., use height
for both width and height) or otherwise supply a sensible default width before
pushing the height segment; ensure both path segments are always present when
either dimension is supplied so the generated Picsum URL is unambiguous.

Comment thread test/providers.ts
hygraph: { url: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=height:200/auto_image/cltsrex89477t08unlckqx9ue' },
caisy: { url: 'https://assets.caisy.io/assets/b76210be-a043-4989-98df-ecaf6c6e68d8/056c27e2-81f5-4cd3-b728-cef181dfe7dc/d83ea6f0-f90a-462c-aebd-b8bc615fdce0pexelsmiguelapadrinan1591056.jpg?h=200' },
bunny: { url: 'https://bunnyoptimizerdemo.b-cdn.net?height=200' },
picsum: { url: 'https://picsum.photos/200' },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Height-only requests produce a square image, not a height-constrained one.

When only height: 200 is specified (no width), the generated URL is https://picsum.photos/200, which Picsum interprets as a 200×200 square image — not a height-only constraint. This is a semantic mismatch with the user's intent. The same URL is produced for width: 200 (line 80).

For a placeholder image provider this is likely acceptable, but it may be worth documenting this limitation or considering emitting https://picsum.photos/200/200 explicitly for clarity.

🤖 Prompt for AI Agents
In `@test/providers.ts` at line 119, The picsum placeholder currently uses the URL
'https://picsum.photos/200' which Picsum treats as a square (200×200) when only
height is intended; update the picsum provider so that when only height is
specified it emits an explicit height/width path (e.g.
'https://picsum.photos/200/200') or adjust the URL generation logic in the
picsum provider to compose `${height}/${height}` when width is undefined; locate
the picsum entry (symbol: picsum) in test/providers.ts and change its url
generation to produce the explicit 'height/height' form or add a note
documenting the limitation if you prefer not to change the URL.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 7, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@nuxt/image@2106

commit: d4e6d37

@danielroe danielroe changed the title feat(provider): add Lorem Picsum placeholder image provider feat(picsum): add Lorem Picsum placeholder image provider Feb 7, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 2.56410% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 6.94%. Comparing base (8b570c8) to head (d4e6d37).

Files with missing lines Patch % Lines
src/runtime/providers/picsum.ts 2.63% 37 Missing ⚠️
src/provider.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main   #2106      +/-   ##
========================================
- Coverage   6.99%   6.94%   -0.05%     
========================================
  Files         78      79       +1     
  Lines       3632    3671      +39     
  Branches     140     141       +1     
========================================
+ Hits         254     255       +1     
- Misses      3329    3367      +38     
  Partials      49      49              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@danielroe danielroe merged commit 13df942 into nuxt:main Feb 7, 2026
8 checks passed
@github-actions github-actions Bot mentioned this pull request Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add provider for lorem picsum

3 participants