Vite Open Graph Meta Tags: Add OG to Your Vite App

How to add og:title, og:image, og:description, and Twitter card meta tags in a Vite application — using vite-plugin-html, SSR, or a static adapter.

The core problem with Vite + SPA

Vite is a build tool, not a rendering framework. If you're building a single-page app (SPA) with Vite + React/Vue/Svelte, your HTML is rendered client-side — social media scrapers only see the initial index.html and won't execute JavaScript to find your OG tags.

You have three options:

  1. Static OG tags in index.html (one set of tags for all pages — works for SPAs where every page shares the same brand)
  2. vite-plugin-html (inject values per build target — works for static sites)
  3. Server-Side Rendering (SSR) with Vite SSR or a framework like Nuxt/SvelteKit (ideal for dynamic per-page OG tags)

Option 1: Static OG tags in index.html

Add OG tags directly to index.html. This applies to ALL pages — fine for a simple app or landing page:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>My Vite App</title>
  <meta name="description" content="A fast app built with Vite." />

  <meta property="og:title"        content="My Vite App" />
  <meta property="og:description"  content="A fast app built with Vite." />
  <meta property="og:image"        content="https://yourdomain.com/og/default.png" />
  <meta property="og:url"          content="https://yourdomain.com" />
  <meta property="og:type"         content="website" />

  <meta name="twitter:card"        content="summary_large_image" />
  <meta name="twitter:title"       content="My Vite App" />
  <meta name="twitter:image"       content="https://yourdomain.com/og/default.png" />

  <link rel="canonical" href="https://yourdomain.com" />
</head>
<body>
  <div id="root"></div>
  <script type="module" src="/src/main.tsx"></script>
</body>
</html>

Option 2: vite-plugin-html with per-page values

For multi-page Vite apps (MPA), use vite-plugin-html to inject different OG values per page:

// vite.config.ts
import { defineConfig } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';

export default defineConfig({
  plugins: [
    createHtmlPlugin({
      inject: {
        data: {
          title: 'My Page',
          description: 'Page description for OG.',
          ogImage: 'https://yourdomain.com/og/page.png',
          canonicalUrl: 'https://yourdomain.com/page',
        },
      },
    }),
  ],
});
<!-- index.html — uses EJS-style template variables -->
<title><%= title %></title>
<meta property="og:title"        content="<%= title %>" />
<meta property="og:description"  content="<%= description %>" />
<meta property="og:image"        content="<%= ogImage %>" />
<meta property="og:url"          content="<%= canonicalUrl %>" />
<meta property="og:type"         content="website" />
<meta name="twitter:card"        content="summary_large_image" />
<meta name="twitter:image"       content="<%= ogImage %>" />

Option 3: Vite SSR for dynamic per-route OG tags

Vite SSR lets you server-render each route with dynamic OG tags. Alternatively, use a framework built on Vite that handles SSR for you:

Verify your Vite app's OG tags

After deploying, paste your URL into OGFixer to preview how your Vite app's links appear on Twitter, LinkedIn, Slack, and Discord — and catch any OG tag issues before they go live.