SolidJS Open Graph Meta Tags: Add OG to Your Solid App

How to add og:title, og:image, og:description and Twitter card tags to SolidJS applications — using @solidjs/meta or custom head management.

How SolidJS handles head tags

SolidJS uses reactive primitives to manage the DOM, but social scrapers don't execute JavaScript — they read raw HTML. This means you need server-side rendering (SSR) for OG tags to work. Use @solidjs/meta with SolidStart for SSR, or inject OG tags in your server response for CSR-only apps.

SolidStart: using @solidjs/meta

Install the package and wrap your app with MetaProvider:

npm install @solidjs/meta
// src/root.tsx
import { MetaProvider } from "@solidjs/meta";

export default function Root() {
  return (
    <MetaProvider>
      {/* your app */}
    </MetaProvider>
  );
}

Then in each route component, use Meta and Title tags:

// src/routes/blog/[slug].tsx
import { Meta, Title } from "@solidjs/meta";
import { useParams } from "@solidjs/router";
import { createResource } from "solid-js";

export default function BlogPost() {
  const params = useParams();
  const [post] = createResource(() => params.slug, fetchPost);

  return (
    <>
      <Title>{post()?.title ?? "Blog"} | My Site</Title>
      <Meta property="og:title" content={post()?.title ?? ""} />
      <Meta property="og:description" content={post()?.excerpt ?? ""} />
      <Meta
        property="og:image"
        content={`https://yourdomain.com/og/${params.slug}.png`}
      />
      <Meta
        property="og:url"
        content={`https://yourdomain.com/blog/${params.slug}`}
      />
      <Meta property="og:type" content="article" />
      <Meta name="twitter:card" content="summary_large_image" />
      <Meta name="twitter:title" content={post()?.title ?? ""} />
      <Meta name="twitter:description" content={post()?.excerpt ?? ""} />
      <Meta
        name="twitter:image"
        content={`https://yourdomain.com/og/${params.slug}.png`}
      />
      <main>
        <h1>{post()?.title}</h1>
        <p>{post()?.body}</p>
      </main>
    </>
  );
}

SolidStart: route-level metadata with createRouteData

For SSR-safe OG tags, fetch data server-side using createRouteData:

// src/routes/product/[id].tsx
import { createRouteData, useRouteData } from "solid-start";
import { Meta, Title } from "@solidjs/meta";

export function routeData({ params }: { params: { id: string } }) {
  return createRouteData(async () => {
    const res = await fetch(`https://api.example.com/products/${params.id}`);
    return res.json();
  });
}

export default function ProductPage() {
  const product = useRouteData<typeof routeData>();

  return (
    <>
      <Title>{product()?.name} - My Store</Title>
      <Meta property="og:title" content={product()?.name ?? ""} />
      <Meta property="og:description" content={product()?.description ?? ""} />
      <Meta property="og:image" content={product()?.imageUrl ?? ""} />
      <Meta property="og:type" content="website" />
      <Meta name="twitter:card" content="summary_large_image" />
      <main>
        <h1>{product()?.name}</h1>
      </main>
    </>
  );
}

Static default OG tags in the root layout

Set fallback OG tags in your root layout so every page has a baseline even if a specific page doesn't override them:

// src/root.tsx
import { MetaProvider, Meta, Title, Link } from "@solidjs/meta";

export default function Root() {
  return (
    <MetaProvider>
      {/* Default / fallback OG tags */}
      <Title>My App</Title>
      <Meta property="og:site_name" content="My App" />
      <Meta property="og:title" content="My App — Default Title" />
      <Meta property="og:description" content="Default description for My App." />
      <Meta property="og:image" content="https://yourdomain.com/og/default.png" />
      <Meta property="og:type" content="website" />
      <Meta name="twitter:card" content="summary_large_image" />
      <Link rel="canonical" href="https://yourdomain.com" />
      {/* ... rest of app */}
    </MetaProvider>
  );
}

CSR-only SolidJS: prerendering or a bot proxy

If you're building a pure client-side SolidJS app without SSR, social scrapers won't see your OG tags — they don't run JavaScript. Options:

  • Enable SSR with SolidStart — the recommended path. Converts your CSR app to SSR without a full rewrite.
  • Use a prerender service like Prerender.io — detects bot user agents and serves pre-rendered HTML.
  • Edge middleware — at Cloudflare Workers or Vercel Edge, detect scraper user agents and return static HTML with OG tags injected.

Verify your SolidJS OG tags

After deploying your SolidJS app, paste your URL into OGFixer to preview how Twitter/X, Slack, Discord, and LinkedIn will render your links — and catch any missing or malformed tags before they go live.