> ## 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.

# Guía del marco: SvelteKit

> Variables de entorno públicas versus protección de la clave API con un punto final +server.ts.

# Guía del marco: SvelteKit

## Variables de entorno público vs privado

SvelteKit distingue explícitamente entre variables públicas (accesibles en el cliente) y privadas (solo servidor) a través de `$env/static/public` / `$env/dynamic/public` vs `$env/static/private` / `$env/dynamic/private`.

```bash .env theme={null}
# Ends up in browser bundle — anyone can see it
PUBLIC_MARKPDF_API_KEY=tu_key_publica

# Only accessible from server-side code (+page.server.ts, +server.ts, hooks.server.ts)
MARKPDF_API_KEY=tu_key_privada
```

Si usa `createConvertStore`/`MarkpdfClient` en un componente `.svelte` (código de cliente), solo puede pasarle una variable `PUBLIC_*`, y esa clave está expuesta en el paquete, como en cualquier SPA.

## Patrón A: clave pública en el cliente (prototipos, herramientas internas)

```svelte theme={null}
<script lang="ts">
  import { PUBLIC_MARKPDF_API_KEY } from "$env/static/public";
  import { MarkpdfClient, createConvertStore } from "@markpdf/svelte";

  const client = new MarkpdfClient({ apiKey: PUBLIC_MARKPDF_API_KEY });
  const convertStore = createConvertStore(client);
</script>
```

<Warning>
  Al igual que con cualquier SPA, esta clave es visible para cualquiera que inspeccione el paquete o el tráfico de la red. Úselo solo si acepta ese riesgo (consulte [consideraciones clave de exposición](/docs/public/es/sdks/react/framework-guide#la-api-key-en-el-navegador), que se aplican de la misma manera aquí).
</Warning>

## Patrón B (recomendado): proxy con `+server.ts`

Mantenga la clave en el servidor y exponga su propio punto final:

```ts src/routes/api/convert/+server.ts theme={null}
import { MARKPDF_API_KEY } from "$env/static/private";
import { MarkpdfClient } from "@markpdf/svelte";
import type { RequestHandler } from "./$types";

const client = new MarkpdfClient({ apiKey: MARKPDF_API_KEY });

export const POST: RequestHandler = async ({ request }) => {
  const form = await request.formData();
  const file = form.get("file") as File;

  const markdown = await client.convertFile(file, { filename: file.name, mode: "fast" });

  return new Response(markdown, { headers: { "content-type": "text/markdown" } });
};
```

Y desde el componente del cliente, cargue el archivo en su propio punto final en lugar de hacerlo directamente en markpdf:

```svelte theme={null}
<script lang="ts">
  let status = "idle";
  let markdown = "";

  async function onFile(e: Event) {
    const file = (e.target as { files?: FileList | null }).files?.[0];
    if (!file) return;

    status = "uploading";
    const form = new FormData();
    form.append("file", file);

    const res = await fetch("/api/convert", { method: "POST", body: form });
    markdown = await res.text();
    status = "success";
  }
</script>

<input type="file" on:change={onFile} />
```

Con este patrón, `createConvertStore` no se aplica en el lado del cliente (no tiene sentido llamarlo contra su propio punto final a menos que también implemente el mismo contrato de progreso). Si necesita un progreso de carga real en su propio punto final, implemente el mismo patrón `XMLHttpRequest` que `createConvertStore` usa internamente, apuntando a `/api/convert` en lugar de API de markpdf.

## Acciones de formulario como alternativa a `+server.ts`

Si el formulario de carga se encuentra en la misma página, una acción de formulario (`+page.server.ts`) es una alternativa sin necesidad de un punto final separado:

```ts src/routes/convert/+page.server.ts theme={null}
import { MARKPDF_API_KEY } from "$env/static/private";
import { MarkpdfClient } from "@markpdf/svelte";
import type { Actions } from "./$types";

const client = new MarkpdfClient({ apiKey: MARKPDF_API_KEY });

export const actions: Actions = {
  default: async ({ request }) => {
    const form = await request.formData();
    const file = form.get("file") as File;
    const markdown = await client.convertFile(file, { filename: file.name, mode: "fast" });
    return { markdown };
  },
};
```

<Tip>
  Utilice acciones de formulario cuando el formulario sea tradicional (envío de página completa, mejora progresiva con `use:enhance`). Utilice un punto final `+server.ts` cuando necesite cargar el progreso a través de `XMLHttpRequest`/`fetch` desde el cliente JS, o cuando otro servicio necesite llamar a su proxy directamente.
</Tip>
