Vue, Nuxt, Quasar & Vite

    Vue SEO that survives every crawler in the room.

    Vue 3, Nuxt, Quasar, and Vite SPAs — all rendered to clean HTML for Google, Bing, GPTBot, ClaudeBot, and every social preview crawler. Without rewriting your reactivity layer.

    −72% nitro server cost on bot traffic4 days avg time-to-index lift7+ sub-frameworks
    Vue.js project on a developer laptop
    Vue
    Make Vue and Nuxt apps fully discoverable across every crawler.
    Nitro server cost on bot traffic
    −72%
    Avg time-to-index lift
    4 days
    useHead capture rate
    100%
    Code changes inside your Vue app
    0

    Vue's reactivity is its strength and, for crawlers, its weakness. Anything bound through Composition API state, anything resolved in `onMounted`, anything fetched after navigation — invisible to bots without JS execution. UpRender solves that without forcing you onto Nuxt SSR or rebuilding around `useFetch`.

    01 / The problem

    Where Vue loses crawlers.

    A Vue SPA mounts at <div id="app"></div>. The runtime composes the UI, fetches data, resolves routes, and updates the DOM reactively. For human users this is the point. For crawlers it's a wall.

    Googlebot will eventually render Vue, but the second-pass renderer skips routes that depend on data fetched in onMounted or async setup() blocks if they don't resolve fast enough. Nuxt SSR helps, but Nuxt requires you to author every data dependency through useFetch or useAsyncData — which is a non-trivial refactor on existing Vue projects.

    Bingbot, Yandex, GPTBot, OAI-SearchBot, ClaudeBot, and every social crawler don't render Vue at all. They see the empty mount point and leave. Your Pinia / Vuex state is invisible. Your reactive <head> updates via useHead arrive after the bot is gone.

    • onMounted data fetches invisible to non-JS bots — product details, reviews, prices
    • Vue Router routes share the same initial HTML — crawlers index one page
    • Pinia / Vuex state never reaches crawlers without SSR
    • v-cloak and Vue transitions hide content from bots with strict render budgets
    • useHead / <Head> meta updates happen client-side, too late for social bots
    • Hydration warnings when Nuxt SSR is partially adopted — silent SEO degradation
    02 / The solution

    How UpRender fixes Vue indexability.

    UpRender sits in front of your Vue or Nuxt app. Bot requests are detected at the edge and proxied through UpRender's render layer, which runs your real Vue app in a real browser, waits for reactivity to settle, captures the final DOM, and returns a clean HTML snapshot. Meta tags from useHead, Pinia-derived content, and <Suspense>-resolved components are all there.

    For Nuxt SSR teams, UpRender works as a complement — it offloads bot traffic from your Nitro server, dramatically reducing the cost of being crawled by GPTBot, ClaudeBot, and the AI search agents that scrape aggressively. For Vue CSR teams, UpRender is the whole solution.

    03 / Benefits

    What changes the day you ship.

    No Nuxt migration required

    Keep your Vite + Vue 3 SPA exactly as it is. No `useFetch` rewrites, no Nuxt directory conventions, no Nitro server to operate.

    Or: offload Nuxt SSR cost

    Already on Nuxt SSR? UpRender absorbs bot traffic so your Nitro server only renders for human visitors — cutting infra cost on aggressive AI crawlers.

    Pinia state in HTML

    Pinia stores populated by `onMounted` actions show up in the bot snapshot, fully serialized into the final HTML. Reviews, prices, user-generated content — all visible.

    Quasar PWA support

    Quasar SPAs and PWAs render cleanly. Capacitor / Cordova hybrid stacks work too — same edge integration.

    AI search citations

    GPTBot, OAI-SearchBot, ClaudeBot, and Claude-SearchBot all get rendered HTML. Your Vue content becomes citable in AI answers and search summaries.

    Social previews finally render

    `useHead` Open Graph and Twitter Card updates are captured into the bot snapshot — link previews work on LinkedIn, Twitter, WhatsApp, Slack, Discord, and Pinterest.

    Vue 2 legacy support

    Still running Vue 2 with Vue Router 3? UpRender renders it cleanly while you plan the Vue 3 migration. SEO doesn't wait for tech debt.

    Suspense and async components resolved

    UpRender waits for `<Suspense>` boundaries and async `setup()` blocks to resolve before snapshotting — bots see the fully-composed page, not loading states.

    No Nitro server to operate

    For Vue CSR teams, UpRender eliminates the need to adopt Nuxt SSR and its Nitro server. No server to scale, no cold starts to optimize, no deployment complexity.

    VitePress documentation indexed

    VitePress doc sites with dynamic content, search, and interactive examples render completely — ensuring your documentation ranks alongside your product pages.

    04 / Real-world scenarios

    Sound familiar?

    01

    You built a Vue 3 SPA and Google only indexes the homepage

    Your Vue Router routes all return the same HTML — a single div#app with a script tag. Google Search Console shows 1 indexed page out of hundreds. UpRender serves each route as distinct, fully-rendered HTML. Indexation coverage jumps from under 5% to over 90% within two weeks.

    02

    Your Nuxt SSR costs are climbing because of AI bot traffic

    GPTBot, OAI-SearchBot, ClaudeBot, and Claude-SearchBot are crawling your Nuxt site tens of thousands of times daily, and every request hits your Nitro server. UpRender absorbs bot traffic at the edge — your Nitro server only renders for paying users. Teams typically see a 60–72% reduction in SSR compute costs.

    03

    Your Vue ecommerce site has broken social previews

    Product links shared on LinkedIn and WhatsApp show blank previews because `useHead` sets OG tags client-side. Social bots don't execute JavaScript. UpRender captures the fully-resolved head tags and serves them to social crawlers — previews render correctly within minutes of deployment.

    04

    You're migrating from Vue 2 to Vue 3 and SEO can't regress

    The Vue 3 migration will take months. In the meantime, both the Vue 2 production app and the new Vue 3 staging routes need to be indexable. UpRender works with both versions simultaneously — one edge worker, two Vue versions, zero SEO regression during the transition.

    05 / Before & after

    What crawlers actually see.

    What crawlers see without UpRender
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>My Vue App</title>
    </head>
    <body>
      <div id="app"></div>
      <script type="module" src="https://uprender.io/src/main.ts"></script>
    </body>
    </html>
    What crawlers see with UpRender
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <title>Luxury Apartments in Barcelona | CityHaus</title>
      <meta name="description" content="Browse 2,400+ luxury apartments..." />
      <meta property="og:title" content="Luxury Apartments in Barcelona" />
      <meta property="og:image" content="/images/barcelona-hero.jpg" />
      <script type="application/ld+json">
        {"@type":"RealEstateListing","name":"Luxury Apartments","price":"€850K"}
      </script>
    </head>
    <body>
      <div id="app">
        <header><nav>Home | Listings | About</nav></header>
        <main>
          <h1>Luxury Apartments in Barcelona</h1>
          <div class="listing-grid">
            <article>2BR Penthouse · Eixample · €1.2M</article>
            <article>3BR Villa · Pedralbes · €2.8M</article>
            <article>1BR Loft · Born · €420K</article>
          </div>
        </main>
      </div>
    </body>
    </html>

    Vue's reactive content resolves into the snapshot. Pinia state, useHead tags, and component output all appear in the HTML crawlers receive.

    06 / Integration

    Vite middleware or edge worker.

    Vue + Vite teams typically use the Vite plugin during development and a Cloudflare Worker or nginx config in production. Nuxt teams use the dedicated Nuxt module.

    nuxt.config.ts — for Nuxt 3 projects.
    // nuxt.config.ts
    export default defineNuxtConfig({
      modules: ['@uprender/nuxt'],
    
      uprender: {
        token: process.env.UPRENDER_TOKEN,
    
        // Offload bot traffic — humans hit Nitro, bots hit UpRender
        crawlers: ['google', 'bing', 'ai', 'social'],
    
        // Recache when Nuxt content changes
        revalidate: { onContentUpdate: true },
      },
    });
    1. 1Install @uprender/nuxt (Nuxt) or @uprender/vite (Vue CSR)
    2. 2Add the module to your nuxt.config.ts or Vite config
    3. 3Set UPRENDER_TOKEN in your env
    4. 4Deploy. UpRender begins serving rendered HTML to bot User-Agents immediately
    5. 5Validate with curl -A 'GPTBot' https://yoursite.com/ — you'll see fully composed HTML
    07 / Works with

    One Vue integration. Every meta-framework.

    Vue 3

    Composition API, Options API, `<script setup>`

    Nuxt 3

    Universal, SPA, hybrid rendering

    Vue 2

    Legacy Vue 2 + Vue Router 3 stacks

    Quasar

    Quasar Framework SPA / PWA / SSR

    Vite + Vue

    Pure Vite SPA setups without Nuxt

    VitePress

    Documentation sites built on Vite

    Gridsome (legacy)

    Still maintained Gridsome 0.x projects

    "The fastest fix we've ever shipped to production. Vue stayed Vue. Crawlers finally got HTML."
    Engineering Lead · UpRender customer · Vue, Nuxt, Quasar & Vite team
    09 / Frequently asked

    The questions teams actually ask.

    Often yes, for two reasons. First, Nuxt SSR runs on your origin — every GPTBot, OAI-SearchBot, ClaudeBot, and Claude-SearchBot crawl costs you Nitro compute. UpRender absorbs bot traffic, dramatically cutting your AI-bot bill. Second, partial-SSR setups (some pages SSR, some client-only) leave gaps that UpRender catches.

    No. Stores are only used during real-user navigation. UpRender's render path is independent — it runs your Vue app in its own browser, captures the resulting HTML, and serves it. Your client store behavior is unaffected.

    Yes. UpRender waits for reactivity to settle before snapshotting, which means `useHead` and `<Head>` updates — including OG tags, JSON-LD, canonical URLs — appear in the final HTML the bot receives.

    Vue 2 with Vue Router 3 is fully supported. Many teams use UpRender as a bridge while migrating to Vue 3, keeping SEO intact during the transition.

    Yes. UpRender's render path waits for `<Suspense>` boundaries to resolve before capturing the snapshot. Async components, lazy imports, and async `setup()` blocks all complete before the HTML is returned to the crawler.

    Both libraries update meta tags client-side. UpRender's rendered HTML captures whatever they set, server-side, before the bot ever sees the page. You don't change how you author meta tags — UpRender just makes sure they reach the crawler.

    Nuxt 3 supports per-route rendering rules (SSR, CSR, ISR, SWR). UpRender works regardless of which mode each route uses — it operates at the edge before Nuxt's rendering pipeline runs. Routes configured as client-only get pre-rendered by UpRender; SSR routes get their bot traffic offloaded.

    Yes. Quasar PWA mode runs client-side only. UpRender serves the rendered HTML to crawlers while the PWA experience — service workers, offline caching, push notifications — continues to work for real users.

    UpRender renders each localized route separately. If you use `vue-i18n` or `@nuxtjs/i18n` with path-based localization (`/en/products`, `/fr/products`), each locale gets its own cached snapshot with the correct language content, hreflang tags, and localized meta data.

    Your turn

    Ship Vue that bots can read.

    Free trial. No credit card. Most Vue teams see their first indexation lift inside 48 hours.

    Other frameworks we support