October 13, 2025
2 min read

Serving a Google Drive Resume on My Domain (Without .pdf)

Serving a Google Drive Resume on My Domain (Without .pdf)

I wanted my resume to live at:

abhinavganeshan.in/resume

and not resume.pdf, not Google Drive’s UI, and not a redirect that changes the URL.

The goal was simple:

  • Clean URL
  • No Google Drive chrome
  • PDF rendered inline
  • Resume updates automatically when I update it in Drive

Below is what worked, what didn’t, and the final approach that solved everything cleanly.


Naive Solution (Works, But Ugly)

Put the PDF in the public folder.

abhinavganeshan.in/resume.pdf

This works, but the .pdf extension was not what I wanted.


Embed Google Drive Preview

// src/app/resume/page.tsx
export default function Page() {
  return (
    <iframe
      src="https://drive.google.com/file/d/FILE_ID/preview"
      className="h-screen w-full"
    />
  );
}

The URL looked fine, but Google Drive’s UI appeared inside the iframe, clashing with the site layout.


Redirects (URL Changes)

async redirects() {
  return [
    {
      source: "/resume",
      destination: "https://drive.google.com/file/d/FILE_ID",
      permanent: false,
    },
  ];
}

This works functionally, but the browser ends up on drive.google.com. The original domain is lost.


Rewrites (Still Doesn’t Work)

async rewrites() {
  return [
    {
      source: "/resume",
      destination: "https://drive.google.com/file/d/FILE_ID",
    },
  ];
}

Google Drive responds with redirects anyway, so the URL still changes.

Adding /preview leads to CORS errors because the browser attempts to fetch cross-origin content directly.


Final Solution: Server-Side Proxy

Instead of letting the browser fetch Google Drive, fetch it from the server.

// app/resume/route.ts

const driveUrl =
  "https://drive.google.com/uc?export=download&id=FILE_ID";

export async function GET() {
  const res = await fetch(driveUrl);

  if (!res.ok || !res.body) {
    return new Response("Failed to fetch PDF", { status: 502 });
  }

  return new Response(res.body, {
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": "inline; filename=Abhinav-Resume.pdf",
    },
  });
}

Why this works

  • No CORS issues – Server-to-server requests are not affected by CORS
  • Clean URL/resume stays /resume
  • Inline rendering – Browser displays the PDF directly
  • Auto-updates – Updating the file in Drive updates the site instantly

Result

abhinavganeshan.in/resume
  • No .pdf
  • No Google Drive UI
  • No redirects
  • No redeploys when the resume changes

When This Pattern Is Useful

  • Resumes
  • PDFs generated in Google Docs
  • Reports
  • Press kits
  • Certificates
  • Any file you want hosted logically on your domain but physically elsewhere

This approach may be slightly overkill, but it’s clean, predictable, and easy to maintain.

AG

Abhinav Ganeshan

Full Stack Developer & Cloud Architect