Tutorial

Screenshot API with Vue.js & Nuxt — SSR, Composables & Pinia

Integrate SnapAPI screenshot capture into Vue 3 and Nuxt 3 applications. Server-side rendering, composables, and Pinia state management examples.

Screenshot API in Nuxt 3 Server Routes

Nuxt 3 server routes provide the cleanest pattern for calling the SnapAPI screenshot endpoint from a Nuxt application, because they run on the server where the API key is safe and the HTTP call does not cross origin restrictions. Create a server route file at server/api/screenshot.get.ts that reads a url query parameter from the H3 event, validates the URL format, calls the SnapAPI endpoint using $fetch or the Node.js native fetch, and returns the PNG response. The Nuxt server route is automatically available at /api/screenshot in the running application and can be called from any Vue component using useFetch or $fetch without exposing the SnapAPI key to the browser. The server route handles CORS automatically since it serves from the same origin as the Nuxt application.

Nuxt 3's useAsyncData composable calls the screenshot server route in server-side rendering context so that the screenshot is included in the initial HTML response. In a Nuxt page component, call const { data: screenshotData } = await useAsyncData('screenshot-' + url, () => $fetch('/api/screenshot', { query: { url } })). Nuxt deduplicates the data fetching between server and client, so the screenshot request fires once on the server and the result is hydrated on the client without a redundant second fetch. For pages with many screenshots, the lazy option defers non-critical screenshots to client-side loading to reduce server response time for the initial page render.

Screenshot API Vue 3 Composable

Vue 3 composables encapsulate the screenshot fetching logic in a reusable function that any component can import. Define a useScreenshot composable that accepts a target URL ref or computed value and returns reactive state including the screenshot URL, loading boolean, and error value. Inside the composable, use watchEffect to trigger a new screenshot fetch whenever the target URL changes. Call the Nuxt API route or the SnapAPI endpoint directly, update the screenshot ref on success, and set the error ref on failure. Components that display screenshot thumbnails import the composable, spread its returned refs into the component's template context, and reactively display loading indicators, error messages, or the screenshot image based on the composable's state. The composable pattern eliminates duplicated screenshot fetching logic across components.

Vue 3 composables that cache screenshot results across component instances use a module-level Map as a simple in-memory cache. Store the fetched image URL or base64 data keyed by the target URL string in the Map after each successful fetch. Subsequent calls to the composable for the same target URL return the cached result immediately without making a new API call. This pattern is appropriate for single-page application contexts where the cached data persists for the lifetime of the browser session. For applications that need cache invalidation or persistence across sessions, replace the module-level Map with a Pinia store that serializes cache entries to sessionStorage or localStorage.

Screenshot API with Pinia in Vue 3

Pinia stores manage screenshot state for Vue 3 applications where multiple components need access to the same screenshot data. Define a useScreenshotStore with state containing a screenshots object mapping URL strings to their status and data, actions for fetching screenshots and clearing stale cache entries, and getters for computing derived values like the count of loading screenshots. Components dispatch the fetchScreenshot action with a target URL and observe the corresponding state through the getter or direct state access. The Pinia store centralizes screenshot caching across all components in the application, preventing duplicate API calls when multiple components request a screenshot for the same URL simultaneously. The store's devtools integration makes it easy to inspect cached screenshots and debug loading state issues during development.

Screenshot API in Vue 3 with the Composition API

Vue 3 Composition API components fetch screenshots in the setup function or script setup block using refs and lifecycle hooks. Define a screenshot ref initialized to null and a loading ref initialized to true. In an onMounted hook, call the SnapAPI server route using fetch or $fetch and update the refs with the result. Display the loading state in the template with a v-if on the loading ref and the screenshot with a v-else binding the screenshot ref to an img src attribute. Handle errors by adding a caught error ref and binding a v-else-if for the error state in the template. The Composition API's explicit data flow makes the screenshot loading lifecycle clear and easy to follow compared to the Options API's implicit property mixing.

Screenshot API Nuxt Image Component Integration

Nuxt Image component integration with SnapAPI-generated screenshots provides automatic lazy loading, responsive srcset generation, and format optimization for screenshot thumbnails displayed in Nuxt applications. After receiving a CDN URL from SnapAPI's url response type, pass the URL to the NuxtImg component with appropriate width and height props matching the screenshot dimensions. Configure the nuxt-image module with a custom provider that routes SnapAPI CDN URLs through Nuxt's image optimization pipeline. The NuxtImg component automatically generates WebP versions of PNG screenshots for browsers that support it, reducing bandwidth usage for screenshot-heavy pages. The built-in lazy loading attribute defers screenshot thumbnail loading until the image enters the viewport, improving initial page load performance for pages with many screenshot cards.

Screenshot API in Vue 3 with Nuxt Middleware

Nuxt 3 route middleware can validate that screenshot-enabled pages receive well-formed URL parameters before attempting to generate screenshots. Define a named middleware function that checks for the presence and format of the url query parameter, redirects to an error page for invalid URLs, and calls next() to allow navigation to proceed for valid URLs. Register the middleware in the page component with definePageMeta to apply the validation to a specific route without affecting the rest of the application. This middleware pattern ensures that SnapAPI is only called with validated input, preventing API credit waste from malformed requests triggered by crawlers, link scrapers, or user input errors. Combine the middleware validation with server-side API route validation for defense in depth against invalid screenshot requests.

Screenshot API Vue 3 Error Boundary Component

Vue 3 applications that display screenshot thumbnails in lists or grids need error boundary components to prevent individual screenshot load failures from breaking the entire page. Vue 3 provides the onErrorCaptured lifecycle hook that catches errors thrown by child component setup functions and async operations. Define a ScreenshotErrorBoundary component that wraps screenshot display components, catches loading errors via onErrorCaptured, and renders a fallback placeholder slot when an error is caught. The fallback slot can display a broken image icon, the target URL text, or a retry button that re-triggers the screenshot fetch. Error boundaries prevent a single 422 error from an unavailable target URL from propagating up and unmounting the parent list component, keeping the rest of the screenshot grid functional when individual URLs are unreachable.

Screenshot API with Vue Router and Dynamic Routes

Vue Router applications that display screenshot pages for dynamically routed URLs handle screenshot fetching in the beforeRouteEnter and beforeRouteUpdate navigation guards to ensure screenshots load correctly on both initial navigation and subsequent route changes. In the beforeRouteUpdate guard, cancel any in-flight screenshot request for the previous route using an AbortController before initiating a new request for the new route target. This prevents race conditions where a slow screenshot response for a previous URL arrives and overwrites the screenshot for the current URL after navigation. The AbortController pattern is especially important for screenshot-heavy applications where users navigate quickly between routes before each screenshot has time to load, creating multiple overlapping in-flight requests that resolve in unpredictable order.