Skip to content

Vue ​

headless-prerender works with any client-rendered Vue 3 (or Vue 2) app using Vue Router in history mode. Your components are unchanged.

When you need it ​

Your index.html mounts into an empty element:

html
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>

Non-JS crawlers see an empty #app. Prerendering returns the rendered markup.

Setup ​

  1. Deploy the built app as static files.

  2. Run the service:

    bash
    headless-prerender serve \
      --port 3000 \
      --allow-origin https://www.example.com \
      --cache-ttl 300000
  3. Route bot traffic to it.

History mode and fallbacks ​

Vue Router history mode needs the server to serve index.html for unknown paths. Keep that fallback for humans; the prerender service loads the same URL in a browser, so it resolves the route the same way the client would.

Waiting for async data ​

If route components fetch data in onMounted / setup, the network-idle wait usually covers it. For slower cases:

bash
headless-prerender serve --extra-wait 400

Or use router.isReady() plus a global flag:

ts
router.isReady().then(() => {
  // optionally wait for your store to hydrate
  (window as any).__PRERENDER_READY__ = true;
});

Meta tags ​

Use @unhead/vue (or vue-meta for Vue 2) to set per-route <title> and <meta property="og:*">. The renderer captures the final <head>, so social previews work.

ts
import { useHead } from "@unhead/vue";

useHead({
  title: product.value.name,
  meta: [
    { property: "og:title", content: product.value.name },
    { property: "og:description", content: product.value.summary },
    { property: "og:image", content: product.value.image },
  ],
});

404 status codes ​

For a real 404, render a status-code meta tag in your not-found route and have the proxy honour it:

vue
<script setup>
import { useHead } from "@unhead/vue";
useHead({ meta: [{ name: "prerender-status-code", content: "404" }] });
</script>

Checklist ​

  • [ ] History-mode fallback to index.html in place
  • [ ] --allow-origin set
  • [ ] --extra-wait tuned for async route data
  • [ ] Per-route head metadata rendered client-side
  • [ ] 404 routes marked
  • [ ] Caching enabled

Released under the MIT License.