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

# Ejemplos

> Casos de uso reales para @markpdf/nextjs: cargar formularios, archivos PDF grandes, BYOS y RAG.

# Ejemplos

## Complete el formulario de carga (Acción del servidor + estado de carga)

```ts app/actions.ts theme={null}
"use server";

import { convertFormData } from "@markpdf/nextjs";

export async function convertUpload(formData: FormData) {
  return convertFormData(formData, {
    apiKey: process.env.MARKPDF_API_KEY!,
    mode: "fast",
    responseFormat: "json",
  });
}
```

```tsx app/upload-form.tsx theme={null}
"use client";

import { useState, useTransition } from "react";
import { convertUpload } from "./actions";

export function UploadForm() {
  const [markdown, setMarkdown] = useState("");
  const [isPending, startTransition] = useTransition();

  return (
    <form action={(formData) => startTransition(async () => {
      const result = await convertUpload(formData);
      setMarkdown(result.markdown);
    })}>
      <input type="file" name="file" accept=".pdf,.docx,.csv" required />
      <button type="submit" disabled={isPending}>
        {isPending ? "Convirtiendo..." : "Convertir"}
      </button>
      {markdown && <pre>{markdown}</pre>}
    </form>
  );
}
```

## PDF grande con rango de páginas

```ts app/actions.ts theme={null}
"use server";

import { convertUrlAction } from "@markpdf/nextjs";

export async function convertSection(url: string, pages: string) {
  return convertUrlAction(url, {
    apiKey: process.env.MARKPDF_API_KEY!,
    pages,
    mode: "fast",
  });
}
```

## BYOS: el usuario sube directamente a tu depósito, solo envías el URL prefirmado

```ts app/actions.ts theme={null}
"use server";

import { getServerClient } from "@markpdf/nextjs";
import { getPresignedPutUrl } from "@/lib/storage"; // your own storage logic

export async function convertToStorage(sourceUrl: string) {
  const client = getServerClient({ apiKey: process.env.MARKPDF_API_KEY! });
  const outputUrl = await getPresignedPutUrl(`converted/${crypto.randomUUID()}.md`);

  const result = await client.convertFromUrl(sourceUrl, {
    responseFormat: "json",
    outputUrl,
  });

  return { outputUrl: result.outputUrl, cached: result.cached };
}
```

Consulte [Compresión](/docs/public/es/concepts/compression) y la [referencia `outputUrl`](/docs/public/es/api/parameters#savalida-byos-output_url).

## Pipeline RAG: vista previa del índice antes de la conversión

```ts app/actions.ts theme={null}
"use server";

import { getServerClient } from "@markpdf/nextjs";

export async function getPdfOutline(url: string) {
  const client = getServerClient({ apiKey: process.env.MARKPDF_API_KEY! });
  const spine = await client.pdfIndex(url);
  return spine.sections; // [{ page, level, text }, ...]
}

export async function convertSelectedSection(url: string, startPage: number, endPage: number) {
  const client = getServerClient({ apiKey: process.env.MARKPDF_API_KEY! });
  return client.convertFromUrl(url, { pages: `${startPage}-${endPage}`, mode: "fast" });
}
```

```tsx app/pdf-explorer.tsx theme={null}
"use client";

import { useState } from "react";
import { getPdfOutline, convertSelectedSection } from "./actions";

export function PdfExplorer({ url }: { url: string }) {
  const [sections, setSections] = useState<Array<{ page: number; level: number; text: string }>>([]);

  return (
    <div>
      <button onClick={async () => setSections(await getPdfOutline(url))}>
        Cargar índice
      </button>
      <ul>
        {sections.map((s) => (
          <li key={s.page} style={{ marginLeft: s.level * 16 }}>
            {s.text} (p. {s.page})
          </li>
        ))}
      </ul>
    </div>
  );
}
```

Este patrón evita convertir un PDF completo de cientos de páginas cuando el usuario solo quiere explorar el índice primero. Consulte el [PDF Índice de agentes de IA](/docs/public/es/concepts/pdf-index-for-ai-agents).

## Ruta pública protegida con tu propia autenticación

```ts app/api/convert/route.ts theme={null}
import { getServerClient } from "@markpdf/nextjs";
import { auth } from "@/lib/auth";
import { NextResponse } from "next/server";

const client = getServerClient({ apiKey: process.env.MARKPDF_API_KEY! });

export async function POST(req: Request) {
  const session = await auth();
  if (!session) return NextResponse.json({ error: "no autorizado" }, { status: 401 });

  const form = await req.formData();
  const file = form.get("file") as File;
  const markdown = await client.convertFile(file, { filename: file.name, mode: "fast" });
  return new NextResponse(markdown, { headers: { "content-type": "text/markdown" } });
}
```

<Note>
  Su propia capa de autenticación (NextAuth, Clerk, self-session, etc.) protege quién puede llamar a su controlador de ruta; está separada de la clave API Flash PDF de Markdown, que solo autentica su backend contra API.
</Note>
