Remix Open Graph Meta Tags: Server-Rendered Meta with meta() Function
Add og:title, og:image, og:description, and Twitter card tags to Remix apps using the meta() export function — with dynamic data from loaders.
Why Remix is great for OG tags
Remix is a full-stack web framework built on server-side rendering. Every route renders on the server, which means social crawlers receive fully hydrated HTML with your <meta> tags already in place. You never have to worry about JavaScript not executing — Remix handles this by design.
Meta tags in Remix are managed through the meta export function at the route level. Each route can define its own metadata, and Remix merges them with parent route meta.
Basic meta() export
Export a meta function from any route file. It receives the loader data and returns an array of meta descriptor objects:
// app/routes/_index.tsx
import type { MetaFunction } from "@remix-run/node";
export const meta: MetaFunction = () => {
return [
{ title: "My Remix Site" },
{ name: "description", content: "My site description." },
{ property: "og:title", content: "My Remix Site" },
{ property: "og:description", content: "My site description." },
{ property: "og:image", content: "https://example.com/og.jpg" },
{ property: "og:url", content: "https://example.com" },
{ property: "og:type", content: "website" },
{ name: "twitter:card", content: "summary_large_image" },
{ name: "twitter:title", content: "My Remix Site" },
{ name: "twitter:description", content: "My site description." },
{ name: "twitter:image", content: "https://example.com/og.jpg" },
];
};
export default function Index() {
return <main>...</main>;
}Dynamic OG tags from loader data
For dynamic pages like blog posts or product pages, load the data in a loader function and access it inside meta via the data parameter:
// app/routes/posts.$slug.tsx
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
export async function loader({ params }: LoaderFunctionArgs) {
const post = await getPost(params.slug);
if (!post) throw new Response("Not Found", { status: 404 });
return json({ post });
}
export const meta: MetaFunction<typeof loader> = ({ data }) => {
if (!data) return [{ title: "Post Not Found" }];
const { post } = data;
return [
{ title: post.title },
{ name: "description", content: post.excerpt },
{ property: "og:title", content: post.title },
{ property: "og:description", content: post.excerpt },
{ property: "og:image", content: post.coverImage },
{ property: "og:url", content: `https://example.com/posts/${post.slug}` },
{ property: "og:type", content: "article" },
{ name: "twitter:card", content: "summary_large_image" },
];
};
export default function PostPage() {
const { post } = useLoaderData<typeof loader>();
return <article>...</article>;
}Root route and default meta
Set a sensible default in app/root.tsx so every page has fallback meta tags. Child routes can override or extend these:
// app/root.tsx
export const meta: MetaFunction = () => [
{
name: "viewport",
content: "width=device-width,initial-scale=1",
},
{ charset: "utf-8" },
{ property: "og:type", content: "website" },
{ name: "twitter:card", content: "summary_large_image" },
];Common Remix OG tag mistakes
- Relative image URLs:
og:imagemust be an absolute HTTPS URL. Use a base URL environment variable:`${process.env.BASE_URL}/og.jpg`. - Missing meta merging: in Remix v2, child meta replaces parent meta by default. Use
matchesto merge parent meta explicitly if needed. - Image dimensions: serve a 1200×630 px image for best rendering across platforms.
- Forgetting og:url: always include a canonical URL to prevent duplicate content issues.
Test your Remix OG tags
Deploy to a public URL and verify each page with platform-specific tools:
- Twitter/X Card Validator
- LinkedIn Post Inspector
- Facebook Sharing Debugger
- OGFixer — preview on Twitter, Slack, Discord simultaneously
Preview your OG tags free at OGFixer.com → Paste your Remix URL to see how it renders on Twitter, LinkedIn, Discord, and Slack.