> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spidra.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Nuxt

> Seamless web scraping, site crawling, SERP search, and document parsing for Nuxt 3 and Nitro applications.

The Spidra Nuxt module (`spidra-nuxt`) brings AI web intelligence directly into Nuxt 3 and Nitro:

* **Nuxt 3 Module**: Built-in configuration with `runtimeConfig` and automatic module registration.
* **Nitro Server Utility**: `useServerSpidra(event)` offers zero-boilerplate client access in server route handlers (`server/api/*`).
* **HMAC Webhook Handler**: `defineSpidraWebhookHandler()` verifies asynchronous crawl and batch signatures in Nitro handlers.
* **Full API Surface**: Scrape, Crawl, SERP Search, Batch Scraping, Document Parsing, Domain Mapping, Turnkey Templates, Presets, and Monitors.

## Installation

```bash theme={null}
npm install spidra-nuxt spidra
```

> [!NOTE]
>
> Get your API key from [app.spidra.io](https://app.spidra.io) under **API Keys**.
> Store it in `.env` or your runtime configuration.

## Configuration

Register the module and credentials in `nuxt.config.ts`:

```ts theme={null}
export default defineNuxtConfig({
  modules: ["spidra-nuxt"],
  runtimeConfig: {
    spidra: {
      apiKey: process.env.SPIDRA_API_KEY,
      webhookSecret: process.env.SPIDRA_WEBHOOK_SECRET,
      // Optional overrides:
      baseUrl: process.env.SPIDRA_BASE_URL,
      maxRetries: 3,
      backoffFactor: 1.0,
    },
  },
});
```

And in your root `.env` file:

```bash theme={null}
SPIDRA_API_KEY=spd_live_your_api_key
SPIDRA_WEBHOOK_SECRET=whsec_your_signing_secret
```

## Quickstart

### 1. In a Nitro Server Route

Use `useServerSpidra(event)` inside any Nitro server API route:

```ts theme={null}
// server/api/scrape.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { url } = await readBody(event);

  const result = await spidra.scrape({
    urls: [{ url }],
    prompt: "Extract product title, price, and description",
    output: "json",
  });

  return { success: true, product: result.data?.[0]?.content };
});
```

### 2. Asynchronous Webhooks

Receive and verify crawl, batch, or monitor webhook events in Nitro:

```ts theme={null}
// server/api/webhooks/spidra.post.ts
import { defineSpidraWebhookHandler } from "spidra-nuxt";

export default defineSpidraWebhookHandler({
  onEvent: async (event, nitroEvent) => {
    console.log(`Verified webhook event: ${event.event}`);

    if (event.event === "crawl.completed") {
      console.log(`Crawl job ${event.jobId} completed!`);
    }
  },
});
```

## Complete Spidra Features Guide

### 1. Scraping with Browser Actions & Proxies

Bypass anti-bot mechanisms with residential proxies and interact with dynamic pages before extraction:

```ts theme={null}
// server/api/scrape-spa.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { url } = await readBody(event);

  const result = await spidra.scrape({
    urls: [{ url }],
    prompt: "Extract dynamic pricing plans and included features",
    output: "json",
    schema: {
      type: "object",
      properties: {
        plans: {
          type: "array",
          items: {
            type: "object",
            properties: {
              planName: { type: "string" },
              monthlyPrice: { type: "number" },
            },
          },
        },
      },
    },
    actions: [
      { type: "click", selector: "button#toggle-annual" },
      { type: "wait", ms: 1500 },
      { type: "scroll", distance: 800 },
    ],
    proxy: {
      type: "residential",
      country: "US",
    },
    waitForSelector: "div.pricing-cards",
    screenshot: true,
  });

  return result;
});
```

### 2. Deep Site Crawling

Initiate recursive domain crawls with depth controls and path filtering:

```ts theme={null}
// server/api/crawl.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { domain } = await readBody(event);

  const crawlJob = await spidra.crawl({
    url: domain,
    maxDepth: 3,
    maxPages: 100,
    allowBackwardLinks: false,
    allowExternalLinks: false,
    includePaths: ["/docs/**", "/guides/**"],
    excludePaths: ["/deprecated/**"],
    ignoreSitemap: false,
    webhook: {
      url: "https://my-nuxt-app.com/api/webhooks/spidra",
    },
  });

  return { jobId: crawlJob.jobId, status: "queued" };
});
```

### 3. Real-Time SERP Web Search

Query web, news, and image indexes to ground AI workflows with fresh search data:

```ts theme={null}
// server/api/search.get.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { q } = getQuery(event);

  const searchResults = await spidra.search({
    query: (q as string) || "Nuxt 3 Nitro server engine",
    sources: ["web", "news"],
    limit: 10,
    filter: {
      domain: ["nuxt.com", "nitro.unjs.io"],
    },
  });

  return searchResults;
});
```

### 4. High-Throughput Batch Scraping

Scrape multiple independent pages in parallel:

```ts theme={null}
// server/api/batch.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { urls } = await readBody(event);

  const batchJob = await spidra.batchScrape({
    urls,
    prompt: "Extract headline, author, and date published",
    output: "json",
    webhook: {
      url: "https://my-nuxt-app.com/api/webhooks/spidra",
    },
  });

  return { jobId: batchJob.jobId, status: "processing" };
});
```

### 5. Fast Domain Link Mapping

Discover all discoverable URLs across a domain without downloading full page bodies:

```ts theme={null}
// server/api/map.get.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { url } = getQuery(event);

  const siteMap = await spidra.map({
    url: (url as string) || "https://nuxt.com",
    limit: 500,
    search: "modules",
  });

  return siteMap;
});
```

### 6. Document Parsing

Extract clean markdown and tables from remote document URLs:

```ts theme={null}
// server/api/parse.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { fileUrl } = await readBody(event);

  const doc = await spidra.parse({
    url: fileUrl,
    prompt: "Extract executive summary and balance sheet data",
  });

  return { markdown: doc.markdown, metadata: doc.metadata };
});
```

### 7. Turnkey AI Templates & Scheduled Monitors

Execute pre-tuned extraction templates and automate recurring scrapes:

```ts theme={null}
// server/api/templates.post.ts
import { useServerSpidra } from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);

  // Execute pre-tuned e-commerce template
  const productData = await spidra.executeTemplate("ecommerce-product", {
    url: "https://store.example.com/product/789",
  });

  // Schedule recurring monitor
  const monitor = await spidra.createMonitor({
    url: "https://status.nuxt.com",
    cron: "0 */6 * * *",
    prompt: "Check for active service disruptions or incidents",
    webhook: {
      url: "https://my-nuxt-app.com/api/webhooks/spidra",
    },
  });

  return { productData, monitorId: monitor.id };
});
```

## Typed Error Handling

Catch and handle granular Spidra errors in Nitro event handlers:

```ts theme={null}
// server/api/scrape-safe.post.ts
import {
  useServerSpidra,
  SpidraError,
  RateLimitError,
  TimeoutError,
  AuthenticationError,
} from "spidra-nuxt";

export default defineEventHandler(async (event) => {
  const spidra = useServerSpidra(event);
  const { url } = await readBody(event);

  try {
    const result = await spidra.scrape({
      urls: [{ url }],
      prompt: "Extract article title and summary",
    });
    return { success: true, data: result.data };
  } catch (error) {
    if (error instanceof RateLimitError) {
      throw createError({
        statusCode: 429,
        statusMessage: `Rate limit exceeded. Retry after ${error.retryAfter}s`,
      });
    } else if (error instanceof AuthenticationError) {
      throw createError({
        statusCode: 401,
        statusMessage: "Invalid Spidra API key",
      });
    } else if (error instanceof TimeoutError) {
      throw createError({
        statusCode: 504,
        statusMessage: "Extraction timed out",
      });
    } else if (error instanceof SpidraError) {
      throw createError({
        statusCode: error.status || 500,
        statusMessage: error.message,
      });
    }

    throw createError({
      statusCode: 500,
      statusMessage: "Internal server error",
    });
  }
});
```

## Related Frameworks

> [card] [Next.js SDK](https://docs.spidra.io/sdks/nextjs.md)
>
> App Router, Pages Router, and Server Actions integration.

> [card] [Remix SDK](https://docs.spidra.io/sdks/remix.md)
>
> Spidra loaders and actions for Remix and React Router.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.