Screenshot API Solid.js Guide 2026

Integrate SnapAPI into Solid.js and SolidStart applications with server functions, createResource, suspense boundaries, and fine-grained reactive screenshot workflows.

Get Your Free API Key

Solid.js and SnapAPI: A Natural Fit

Solid.js has earned a dedicated following among performance-conscious frontend developers. Its fine-grained reactivity model — where signals update only the specific DOM nodes that depend on them rather than re-rendering entire component trees — makes it the fastest mainstream JavaScript framework for UI rendering. When you integrate screenshot API calls into a Solid.js application, that same reactivity model ensures that screenshot loading states, results, and errors update the minimum possible amount of DOM without any virtual diffing overhead.

SolidStart, the full-stack meta-framework for Solid.js, adds server functions and server-side rendering that make SnapAPI integration straightforward and secure. This guide covers client-side integration with createResource, server function patterns with SolidStart, suspense boundary handling, and fine-grained reactive screenshot queues.

createResource for Screenshot Data Fetching

Solid.js's createResource primitive is the standard pattern for async data fetching. It integrates naturally with Suspense and creates a reactive signal that updates when the fetch completes:

import { createSignal, createResource, Show, Suspense } from 'solid-js'

const fetchScreenshot = async (url) => {
  if (!url) return null
  const res = await fetch('/api/screenshot', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url, width: 1280, height: 800, format: 'png' })
  })
  if (!res.ok) throw new Error('Screenshot failed')
  return res.json()
}

function ScreenshotCapture() {
  const [url, setUrl] = createSignal('')
  const [targetUrl, setTargetUrl] = createSignal(null)
  const [screenshot] = createResource(targetUrl, fetchScreenshot)

  return (
    <div>
      <input
        value={url()}
        onInput={e => setUrl(e.target.value)}
        placeholder="https://example.com"
      />
      <button onClick={() => setTargetUrl(url())}>Capture</button>
      <Suspense fallback={<p>Capturing...</p>}>
        <Show when={screenshot()}>
          <img src={screenshot().url} alt="Screenshot" />
        </Show>
      </Suspense>
    </div>
  )
}

SolidStart Server Functions

SolidStart server functions run exclusively on the server, keeping your API key secure. Create a server function for screenshot capture:

// src/routes/api/screenshot.ts
import { json } from '@solidjs/router'
import server$ from 'solid-start/server'

export const captureScreenshot = server$(async (url, options = {}) => {
  const res = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.SNAPAPI_KEY,
    },
    body: JSON.stringify({ url, width: 1280, height: 800, format: 'png', ...options }),
  })
  if (!res.ok) throw new Error('Screenshot capture failed')
  return res.json()
})

Call the server function directly from your Solid.js component — SolidStart handles the client-server boundary automatically, serializing arguments and deserializing the response:

import { createSignal, createResource } from 'solid-js'
import { captureScreenshot } from './api/screenshot'

function App() {
  const [url, setUrl] = createSignal('')
  const [shot, { refetch }] = createResource(
    () => url(),
    (u) => u ? captureScreenshot(u) : Promise.resolve(null)
  )
  return (
    <div>
      <input value={url()} onInput={e => setUrl(e.target.value)} />
      <button onClick={refetch}>Capture</button>
      <Show when={shot()}>
        <img src={shot().url} />
      </Show>
    </div>
  )
}

Fine-Grained Reactive Screenshot Queue

For batch screenshot workflows — capturing a list of URLs and displaying results as they complete — Solid.js's fine-grained reactivity shines. Use a reactive store to manage the queue and update individual results without re-rendering the entire list:

import { createStore } from 'solid-js/store'
import { For } from 'solid-js'

const [queue, setQueue] = createStore([])

async function processQueue(urls) {
  setQueue(urls.map(url => ({ url, status: 'pending', result: null })))
  for (let i = 0; i < urls.length; i++) {
    setQueue(i, 'status', 'loading')
    try {
      const result = await captureScreenshot(urls[i])
      setQueue(i, { status: 'done', result })
    } catch {
      setQueue(i, 'status', 'error')
    }
  }
}

function QueueDisplay() {
  return (
    <For each={queue}>{(item) =>
      <div>
        <p>{item.url} — {item.status}</p>
        <Show when={item.result}>
          <img src={item.result.url} width={300} />
        </Show>
      </div>
    }</For>
  )
}

Deploying SolidStart Screenshot Services

SolidStart deploys to Vercel, Netlify, Cloudflare Workers, and Node.js with adapter-specific configuration. For Cloudflare Workers deployment, ensure your server functions use only Web API-compatible fetch (no Node.js built-ins). SnapAPI uses standard HTTP fetch under the hood, making it fully compatible with the Cloudflare Workers runtime. Set SNAPAPI_KEY as a Cloudflare secret using wrangler, and your SolidStart screenshot service will run at the edge with minimal latency. Sign up for a free API key at snapapi.pics and ship your first Solid.js screenshot feature today.

Error Handling and Loading States in Solid.js

Solid.js provides the ErrorBoundary component for catching errors in createResource calls. Wrap your screenshot display in an ErrorBoundary to handle API failures gracefully:

import { ErrorBoundary, Suspense } from 'solid-js'

function ScreenshotWithErrorHandling() {
  return (
    <ErrorBoundary fallback={(err) =>
      <div class="error">
        <p>Screenshot failed: {err.message}</p>
        <button onClick={() => window.location.reload()}>Retry</button>
      </div>
    }>
      <Suspense fallback={<div class="spinner">Capturing screenshot...</div>}>
        <ScreenshotDisplay />
      </Suspense>
    </ErrorBoundary>
  )
}

Solid.js Store for Multi-URL Screenshot Management

When building a dashboard that needs to display screenshots of multiple URLs simultaneously — a competitor monitoring tool, a multi-site preview, or a QA dashboard — Solid.js stores with fine-grained updates provide a performance advantage over React state management. Each screenshot result updates only its specific store entry, and Solid.js renders only the affected DOM nodes rather than reconciling an entire list:

import { createStore, produce } from 'solid-js/store'
import { For, Show } from 'solid-js'

const [captures, setCaptures] = createStore({})

async function captureAll(urls) {
  urls.forEach(url => setCaptures(url, { status: 'loading', img: null }))
  await Promise.all(urls.map(async url => {
    try {
      const res = await fetch('/api/screenshot', {
        method: 'POST',
        body: JSON.stringify({ url, width: 1280, height: 800 }),
        headers: { 'Content-Type': 'application/json' }
      })
      const data = await res.json()
      setCaptures(url, { status: 'done', img: data.url })
    } catch {
      setCaptures(url, 'status', 'error')
    }
  }))
}

function CaptureGrid({ urls }) {
  return (
    <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px">
      <For each={urls}>{url =>
        <div>
          <p>{url}</p>
          <Show when={captures[url]?.status === 'done'}>
            <img src={captures[url].img} style="width:100%" />
          </Show>
          <Show when={captures[url]?.status === 'loading'}>
            <p>Loading...</p>
          </Show>
        </div>
      }</For>
    </div>
  )
}

SolidStart API Route with Rate Limiting

Protect your SnapAPI quota by adding rate limiting to your SolidStart API route. A simple in-memory rate limiter per IP address prevents abuse:

// src/routes/api/screenshot.ts
import { json } from '@solidjs/router'
import type { APIEvent } from '@solidjs/start/server'

const rateMap = new Map()

export async function POST(event: APIEvent) {
  const ip = event.request.headers.get('x-forwarded-for') || 'unknown'
  const now = Date.now()
  const entry = rateMap.get(ip) || { count: 0, reset: now + 60000 }
  if (now > entry.reset) { entry.count = 0; entry.reset = now + 60000 }
  if (entry.count >= 10) return json({ error: 'Rate limited' }, { status: 429 })
  entry.count++
  rateMap.set(ip, entry)

  const body = await event.request.json()
  const res = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: { 'X-API-Key': process.env.SNAPAPI_KEY!, 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
  return json(await res.json(), { status: res.status })
}

Performance Comparison: Solid.js vs React for Screenshot UIs

Screenshot-heavy UIs benefit from Solid.js's fine-grained reactivity. In a React application rendering 50 screenshot thumbnails where one loads, React reconciles the entire list even though only one item changed. Solid.js updates only the specific img element for the completed screenshot. For screenshot grid UIs with frequent updates — a live monitoring dashboard capturing dozens of URLs in parallel — this difference is measurable: Solid.js maintains smooth 60fps rendering while React may introduce frame drops from unnecessary reconciliation work. If your use case involves displaying many screenshot results concurrently with frequent updates, Solid.js is a compelling choice. Sign up for your free SnapAPI key at snapapi.pics and start building your Solid.js screenshot integration today.

Authentication, Security, and Enterprise Data Handling

Many of the most valuable screenshot use cases involve authenticated pages — dashboards behind login walls, analytics platforms requiring session tokens, internal tools accessible only via corporate SSO. SnapAPI supports authenticated page capture through cookie injection: you pass a JSON array of cookie objects (name, value, domain, path) in the request body, and SnapAPI loads those cookies into the Chromium session before navigating to the target URL. This allows you to capture authenticated dashboard pages without exposing credentials in the URL or requiring any special integration with your authentication system.

For enterprise deployments, SnapAPI supports custom request headers that allow passing Bearer tokens, API keys, and proprietary authentication headers required by your internal authentication middleware. The Chromium session that renders each page is fully isolated — no cookies or session data carry over between requests, and no data from one customer's captures is ever visible to another. All network traffic between your application and the SnapAPI endpoint is encrypted over TLS 1.3. Screenshot images stored on our CDN are addressed by content hash, making URLs effectively unguessable without advance knowledge of the capture parameters.

For teams in regulated industries — financial services, healthcare, legal, government — that require zero cloud retention of screenshot content, SnapAPI supports a binary streaming response mode where screenshot data is returned directly in the HTTP response body without being stored on our CDN infrastructure at any point. You receive the raw PNG or PDF bytes in the response and store them directly in your own infrastructure — an S3 bucket, a GCS bucket, or an on-premises document vault. This mode satisfies the strictest data residency and retention requirements without any custom infrastructure on your end beyond your existing cloud storage. Contact our team at snapapi.pics to discuss enterprise deployment options, data processing agreements, and volume pricing for high-scale production use cases.