Advanced

Contributing Providers

Learn how to contribute new file providers to Nuxt PDF Kit

Contributing New Providers

Want to add support for OneDrive, Dropbox, S3, or another file storage service? This guide will walk you through the process!

Overview

Adding a new provider involves three main steps:

  1. Add the provider type to the TypeScript definitions
  2. Create the transformation logic in the composable
  3. Add a server route (if needed for CORS/authentication)

Step 1: Add Provider Type

Edit src/runtime/types.ts to add your new provider:

// Before
export type PdfProvider = "url" | "gdrive" | "custom";

// After
export type PdfProvider = "url" | "gdrive" | "onedrive" | "custom";

Step 2: Add Transformation Logic

Edit src/runtime/composables/usePdfKitProvider.ts:

/**
 * Transform OneDrive share link to direct download URL
 */
function transformOneDrive(src: string, config?: ProviderConfig): string {
  // Clean the share ID
  const shareId = src.trim();

  // Get proxy route from config or use default
  const proxyRoute = config?.baseUrl || "/pdf-proxy/onedrive";

  return `${proxyRoute}/${shareId}.pdf`;
}

// Add to the main function
export function usePdfKitProvider(
  provider: PdfProvider = "url",
  src: string,
  config?: ProviderConfig,
): string {
  if (!src) {
    console.warn("[nuxt-pdf-kit] Empty src provided to usePdfKitProvider");
    return "";
  }

  switch (provider) {
    case "gdrive":
      return transformGoogleDrive(src, config);
    case "onedrive": // Add this
      return transformOneDrive(src, config);
    case "custom":
      return transformCustom(src, config);
    case "url":
    default:
      return src;
  }
}

Step 3: Create Server Route (Optional)

If your provider needs CORS handling or authentication, create a server route:

Create the route file

src/runtime/server/routes/pdf-proxy/onedrive/[id].ts:

import {
  createError,
  defineEventHandler,
  sendStream,
  setResponseHeader,
} from "h3";

export default defineEventHandler(async (event) => {
  // 1. Extract file ID from URL
  const path = event.path || event.node.req.url || "";
  const match = path.match(/\/pdf-proxy\/onedrive\/([^/]+?)(?:\.pdf)?$/);
  const shareId = match ? match[1] : "";

  if (!shareId) {
    throw createError({
      statusCode: 400,
      statusMessage: "OneDrive share ID is missing",
    });
  }

  // 2. Construct OneDrive download URL
  // Example: Convert share link to direct download
  const oneDriveUrl = `https://api.onedrive.com/v1.0/shares/${shareId}/root/content`;

  try {
    // 3. Fetch from OneDrive
    const response = await fetch(oneDriveUrl, {
      headers: {
        "User-Agent": "Mozilla/5.0...",
        Accept: "*/*",
      },
      redirect: "follow",
    });

    if (!response.ok) {
      throw createError({
        statusCode: response.status,
        statusMessage: `OneDrive Error: ${response.statusText}`,
      });
    }

    // 4. Check Content-Type
    const contentType = response.headers.get("content-type");
    if (contentType && !contentType.includes("application/pdf")) {
      throw createError({
        statusCode: 502,
        statusMessage: "OneDrive did not return a PDF file",
      });
    }

    // 5. Set response headers
    setResponseHeader(event, "Content-Type", "application/pdf");
    setResponseHeader(event, "Cache-Control", "public, max-age=86400");
    setResponseHeader(event, "Access-Control-Allow-Origin", "*");

    // 6. Stream the response
    if (!response.body) {
      throw createError({
        statusCode: 500,
        statusMessage: "Empty response from OneDrive",
      });
    }

    return sendStream(event, response.body);
  } catch (error: any) {
    console.error("[nuxt-pdf-kit] OneDrive error:", error.message);

    if (error.statusCode) {
      throw error;
    }

    throw createError({
      statusCode: 500,
      statusMessage: error.message || "Internal Server Error",
    });
  }
});

Register the route

Edit src/module.ts to register your server route:

// Add server routes for providers
nuxt.hook("nitro:config", (nitroConfig) => {
  nitroConfig.handlers = nitroConfig.handlers || [];

  // Google Drive proxy route
  nitroConfig.handlers.push({
    route: "/pdf-proxy/gdrive/**",
    handler: resolver.resolve("./runtime/server/routes/pdf-proxy/gdrive/[id]"),
  });

  // OneDrive proxy route (ADD THIS)
  nitroConfig.handlers.push({
    route: "/pdf-proxy/onedrive/**",
    handler: resolver.resolve(
      "./runtime/server/routes/pdf-proxy/onedrive/[id]",
    ),
  });
});

Step 4: Add Tests

Create a test file test/providers.test.ts:

import { describe, it, expect } from "vitest";
import { usePdfKitProvider } from "../src/runtime/composables/usePdfKitProvider";

describe("usePdfKitProvider", () => {
  it("transforms OneDrive share ID correctly", () => {
    const result = usePdfKitProvider(
      "onedrive",
      "u!aHR0cHM6Ly8xZHJ2Lm1zL2IvcyFBcXRhYmNkZWY",
    );

    expect(result).toBe(
      "/pdf-proxy/onedrive/u!aHR0cHM6Ly8xZHJ2Lm1zL2IvcyFBcXRhYmNkZWY.pdf",
    );
  });

  it("uses custom baseUrl for OneDrive", () => {
    const result = usePdfKitProvider("onedrive", "share-123", {
      baseUrl: "/custom-proxy",
    });

    expect(result).toBe("/custom-proxy/share-123.pdf");
  });
});

Step 5: Add Documentation

Create documentation for your provider in docs/content/en/5.advanced/2.providers.md:

### OneDrive Provider

Load PDFs from OneDrive share links.

\`\`\`vue
<template>
<NuxtPdfKit
    provider="onedrive"
    src="u!aHR0cHM6Ly8xZHJ2Lm1zL2IvcyFBcXRhYmNkZWY"
  />
</template>
\`\`\`

**How to get OneDrive Share ID:**

1. Right-click your file in OneDrive
2. Click "Share" → "Copy link"
3. Extract the share ID from the URL
4. Use that ID as the `src` prop

Step 6: Submit Pull Request

  1. Fork the repository on GitHub
  2. Create a feature branch: git checkout -b feat/onedrive-provider
  3. Commit your changes: git commit -m "feat: add OneDrive provider support"
  4. Push to your fork: git push origin feat/onedrive-provider
  5. Open a Pull Request with:
    • Clear description of the provider
    • Usage examples
    • Any limitations or known issues

Provider Checklist

Before submitting your PR, make sure:

  • Provider type added to types.ts
  • Transformation logic added to usePdfKitProvider.ts
  • Server route created (if needed)
  • Server route registered in module.ts
  • Tests added and passing
  • Documentation added
  • Example usage in playground
  • TypeScript types are correct
  • No lint errors

Best Practices

Error Handling

Always provide clear error messages:

if (!fileId) {
  throw createError({
    statusCode: 400,
    statusMessage: "File ID is missing. Please provide a valid share link.",
  });
}

Logging

Use consistent logging format:

console.log("[nuxt-pdf-kit] OneDrive - Processing file:", fileId);
console.error("[nuxt-pdf-kit] OneDrive error:", error.message);

Caching

Set appropriate cache headers:

// Cache for 24 hours
setResponseHeader(event, "Cache-Control", "public, max-age=86400");

// Or disable caching for sensitive files
setResponseHeader(
  event,
  "Cache-Control",
  "no-cache, no-store, must-revalidate",
);

Security

  • Never expose API keys or secrets in client-side code
  • Validate all user inputs
  • Use HTTPS for all external requests
  • Set appropriate CORS headers

Need Help?

  • Discord: Join our community server
  • GitHub Issues: Open an issue for questions
  • Email: [email protected]

We're excited to see what providers you'll add! 🚀

Copyright © 2026