Tutorial

Screenshot and PDF Generation in Nuxt 3 with SnapAPI

April 2026 — 7 min read

Nuxt 3 is the full-stack Vue framework that combines server-side rendering, static site generation, and serverless API routes into a single cohesive development experience. Its server routes -- defined in the server/api/ directory -- run on Node.js and handle API logic without any separate backend setup. In this tutorial, you will add screenshot and PDF generation to a Nuxt 3 application using SnapAPI, protecting the endpoint with Nuxt's H3 event handler utilities and returning binary responses efficiently.

Why Nuxt Server Routes for Screenshot Generation

Nuxt 3's server routes execute entirely on the server side, making them the correct location for any operation that involves secret API keys. When your Nuxt application needs to generate a screenshot, the browser should never see your SnapAPI key. The server route receives the target URL from the client, validates it, calls SnapAPI using the key stored in a Nuxt runtime config environment variable, and returns the binary screenshot data. This architecture keeps credentials secure and gives you full control over which URLs your application is allowed to screenshot.

Creating the Server Route

Create a file at server/api/screenshot.get.ts. The filename suffix .get.ts restricts the route to GET requests. The route handler receives an H3 event object. Use the getQuery utility from H3 to extract the target URL from the query string. Validate the URL using the native URL constructor and reject any URL using non-HTTP schemes. Read your SnapAPI key from the Nuxt runtime configuration using useRuntimeConfig(). Then use $fetch or the native fetch API to call SnapAPI with your key in the Authorization header. Return the response buffer to the client with the appropriate Content-Type header set using H3's setHeader utility.

Nuxt Runtime Config for Secret Management

Nuxt 3's runtime configuration system distinguishes between public config exposed to the browser and private config accessible only in server-side code. Define your SnapAPI key in nuxt.config.ts under the runtimeConfig object's root (not public) key. This ensures the key is available in server routes via useRuntimeConfig() but is never serialized into the client bundle. In your deployment environment, override the runtime config value using the corresponding environment variable, following Nuxt's automatic environment variable mapping convention of prefixing the key name with NUXT_.

Handling Binary Responses in Nuxt

Nuxt server routes return JSON by default. To return binary image data, use H3's setHeader to set the Content-Type to image/png or application/pdf, then return the raw buffer from your SnapAPI fetch call. Nuxt's H3 framework correctly serializes Buffer objects as binary HTTP responses without any additional configuration. For PDF responses, add a Content-Disposition header with the attachment directive to trigger a download prompt in the browser rather than attempting to render the PDF inline.

Using the Screenshot Route in Nuxt Components

From any Nuxt page or component, call the screenshot route using Nuxt's useFetch composable or the $fetch utility. Set the responseType option to 'blob' to receive the binary PNG or PDF as a JavaScript Blob object. Use the Blob to create an object URL with URL.createObjectURL and bind it to an img element's src attribute for inline display, or trigger a download by programmatically clicking an anchor element with the object URL as the href and a filename in the download attribute. This pattern works identically in both the browser rendering environment and Nuxt's server-side rendering context.

Deploying to Vercel and Netlify

Nuxt 3 server routes deploy automatically to Vercel serverless functions and Netlify functions with zero configuration. Run nuxt build to produce a deployment-ready output directory. Set your NUXT_SNAP_API_KEY environment variable in your deployment platform's dashboard. Each screenshot request spins up a serverless function invocation, calls SnapAPI, and returns the result -- fully managed, infinitely scalable, and billed only for actual usage. There is no server to provision, no container to manage, and no headless browser to maintain on your deployment infrastructure.

Advanced Nuxt 3 Screenshot Patterns

Beyond the basic server route pattern, several advanced Nuxt 3 integration patterns are worth implementing for production screenshot services. These patterns address performance, caching, multi-tenancy, and the nuances of Nuxt's rendering modes.

Nitro Task Queue for Batch Screenshot Jobs

Nuxt 3's Nitro server engine supports scheduled tasks and background job processing through its experimental tasks API. For applications that need to generate screenshots in batch -- capturing dozens or hundreds of URLs periodically -- Nitro tasks provide a clean server-side execution environment. Define a Nitro task that reads a list of URLs from your database, calls SnapAPI for each URL with controlled concurrency using a Promise pool pattern, and stores the resulting images in your cloud storage bucket. Schedule the task to run nightly using Nitro's cron-style task scheduler. The entire batch process runs server-side without blocking the user-facing Nuxt application, and results are available for client-side rendering as soon as the task completes.

Nuxt Image Integration

The nuxt/image module provides optimized image delivery with automatic format conversion, lazy loading, and responsive sizing. Screenshots generated by SnapAPI and stored in cloud storage integrate seamlessly with nuxt/image as external image sources. Configure your SnapAPI storage bucket as a nuxt/image provider in your nuxt.config.ts. Screenshots served through nuxt/image are automatically converted to WebP for supporting browsers, resized for different viewports, and served through Nuxt's image CDN with appropriate cache headers. The result is faster screenshot delivery with smaller file sizes without any additional optimization code in your application.

Screenshot Caching with Nuxt's useStorage

Nuxt 3's useStorage composable provides access to Nitro's unified storage layer, which supports Redis, filesystem, and in-memory backends depending on your deployment environment. Use useStorage in your screenshot server route to cache SnapAPI responses by URL hash. Check the storage layer for a cached screenshot before calling SnapAPI. On a cache miss, call SnapAPI, store the result in Nitro storage with your chosen TTL, and return it. On a cache hit, return the stored screenshot immediately. This caching layer reduces SnapAPI API credit consumption and dramatically improves response times for repeated screenshot requests of the same URL.

Open Graph Image Generation with Nuxt OG Image

The nuxt/og-image community module generates Open Graph images for your Nuxt pages using a Vue component rendered server-side. For teams already using nuxt/og-image for template-based OG images, SnapAPI provides a complementary approach for generating OG images from live web pages rather than templates. Use SnapAPI when you need the OG image to capture the actual rendered state of a page -- a data visualization, a user-generated content post, a product configurator -- rather than a static design template. Both approaches can coexist in the same Nuxt application, with nuxt/og-image handling template-based pages and SnapAPI handling pages where the live rendered state is the desired OG image content.

Testing Nuxt Screenshot Routes

Nuxt 3 server routes can be tested using Nuxt's built-in test utilities from the @nuxt/test-utils package. The setup function initializes a test Nuxt application instance, and $fetch from the test utilities calls your server routes directly without a real HTTP server. For screenshot route tests, mock the SnapAPI fetch call using Vitest's vi.spyOn on the global fetch to return a predetermined PNG buffer. Your test assertions verify that the route returns a 200 response with the correct Content-Type header, that invalid URLs return a 400 response, and that unauthorized requests return a 401 when your authentication middleware is active. Run the full test suite as part of your Nuxt CI pipeline to catch regressions in screenshot route behavior before they reach production users.

For end-to-end testing of the complete screenshot flow including the actual SnapAPI call, use a dedicated test SnapAPI key with a small monthly quota and run these tests only on your staging deployment rather than in every CI build. This approach validates the full integration including SnapAPI's real rendering behavior for your specific target URLs without burning production API credits on every commit. Sign up for a free SnapAPI account at snapapi.pics to get started with both unit testing and integration testing of your Nuxt screenshot feature.

Nuxt 3 teams building screenshot features into their applications benefit from SnapAPI's simple REST interface that requires no SDK and works identically across all Nuxt deployment targets including Vercel, Netlify, Fly.io, Cloudflare Workers, and self-hosted Node.js servers. The API returns standard binary PNG or PDF data that Nuxt server routes can forward to clients or persist to cloud storage using any Node.js-compatible storage library. Create your free SnapAPI account at snapapi.pics and have your first Nuxt screenshot route returning real captures within minutes of setup.