Why Vercel + Accept: text/markdown Is the Best Way to Serve Markdown from Next.js & SvelteKit
See why using the Accept header on Vercel is the cleanest way to serve Markdown from Next.js and SvelteKit, and how accept-md automates the setup.
accept-md team
If you're deploying Next.js or SvelteKit to Vercel and need Markdown representations of your pages—for AI crawlers, documentation exports, or data pipelines—the simplest and most scalable pattern is to use the HTTP Accept header.
Instead of adding a second site, running Puppeteer, or bolting on a custom server, you can let Vercel handle routing while a small handler converts HTML → Markdown when clients send Accept: text/markdown.
Why Vercel is a perfect match
Vercel gives you:
- Native support for Next.js and SvelteKit
- Rewrites/middleware (Next.js) and hooks (SvelteKit)
- Serverless and edge runtimes with automatic scaling
That means you can:
- Keep your existing routes
- Let Vercel route
Accept: text/markdowntraffic to a handler - Keep everything in one deployment—no separate "markdown export" service
The Accept header pattern on Vercel
The pattern is simple:
# Normal HTML
curl https://your-app.vercel.app/docs
# Markdown representation
curl -H "Accept: text/markdown" https://your-app.vercel.app/docs
Behind the scenes:
- Vercel matches the request to your app.
- A rewrite/middleware (Next.js) or
handlehook (SvelteKit) seesAccept: text/markdown. - The request is routed to
/api/accept-md/.... - The handler fetches the original page HTML and converts it to Markdown.
Next.js on Vercel
On Next.js, the flow looks like:
next.config.jsrewritesAccept: text/markdownto an internal handler.- The handler uses
accept-md-runtimeto:- Fetch
https://your-app.vercel.app/pathas HTML. - Strip nav/footer/UI chrome.
- Extract metadata to YAML frontmatter.
- Preserve JSON-LD as code blocks.
- Fetch
Vercel is a great fit here:
- Internal fetches stay inside Vercel's network.
- Serverless functions scale automatically.
- No need for a separate markdown export service.
SvelteKit on Vercel
On SvelteKit, the same idea uses hooks instead of middleware:
- A
+serverroute undersrc/routes/api/accept-md/[...path]generates Markdown. - A
hooks.serverhandle rewritesAccept: text/markdownrequests to that route. - Vercel's SvelteKit adapter runs both pieces with no extra configuration.
With accept-md, this is generated for you:
npx accept-md init
From a SvelteKit project root, this command:
- Detects
routes/orsrc/routes/ - Creates the API route for Markdown
- Creates or wraps
src/hooks.server.(ts|js)to route markdown requests - Adds
accept-md.config.jsfor shared configuration
Why not a custom server or Puppeteer?
On Vercel, custom Node servers are discouraged for good reason:
- They bypass Vercel's optimized runtimes.
- You lose out on automatic scaling and routing.
- Deployments become more complex and fragile.
Puppeteer has similar issues:
- Heavy binaries and cold starts
- High memory usage
- Awkward fit for serverless functions
By contrast, the Accept header pattern:
- Uses standard Vercel primitives (rewrites, middleware, hooks).
- Keeps your app fully compatible with Vercel's platform.
- Adds minimal overhead—just one extra handler.
accept-md: the Vercel-native implementation
accept-md is designed to work out of the box on Vercel:
- For Next.js:
- Adds rewrites in
next.config(preferred) or middleware. - Creates a handler that understands Vercel's internal headers and deployment URLs.
- Adds rewrites in
- For SvelteKit:
- Creates the
+serverhandler. - Wires up
hooks.serversoAccept: text/markdownis routed correctly.
- Creates the
- In both cases:
- Caching respects builds and revalidation.
- No custom server is required.
Once it's set up, your Vercel deployment can serve both HTML and Markdown from the same URLs, depending on the Accept header.
Conclusion
If you're on Vercel with Next.js or SvelteKit and need Markdown:
- Use the Accept header, not a separate service.
- Let Vercel handle routing and scaling.
- Use accept-md to wire up handlers and config automatically.
That combination—Vercel + Accept header + accept-md—gives you a production-ready Markdown API with almost zero friction and no changes to your existing pages.