Skip to content

Remix Links and Meta — SEO and Head Management

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Remix Links and Meta. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Remix links and meta: manage per-route SEO metadata, add stylesheets and link tags, and optimize for search engines with the meta and links exports.

In this lesson, you'll use Remix's meta and links exports to manage SEO metadata, stylesheets, favicons, and other <head> elements per route.

What You'll Learn

How to export meta for SEO tags, links for stylesheets and link elements, merge parent and child metadata, and add Open Graph tags.

Why It Matters

Each page needs unique meta tags for search engines and social media. Remix's per-route meta and links let you control this without third-party libraries.

Real-World Use

DodaZIP's public pages use Remix meta for custom title, description, and Open Graph tags per route, improving search visibility and social sharing.

flowchart LR
    A[Route] --> B[meta Export]
    A --> C[links Export]
    B --> D[Title, Description, OG]
    C --> E[Stylesheets, Fonts]
    D --> F[ Element]
    style A fill:#121212,color:#fff

Meta Export

import { type MetaFunction } from "@remix-run/node";

export const meta: MetaFunction = () => {
  return [
    { title: "About Us — DodaTech" },
    { name: "description", content: "Learn about DodaTech's mission to teach programming with security." },
    { property: "og:title", content: "About DodaTech" },
    { property: "og:description", content: "We teach programming through practical, security-focused tutorials." },
    { property: "og:type", content: "website" },
  ];
};
import { type LinksFunction } from "@remix-run/node";

export const links: LinksFunction = () => [
  { rel: "canonical", href: "https://dodatech.com/about" },
  { rel: "icon", href: "/favicon.ico", type: "image/x-icon" },
  {
    rel: "stylesheet",
    href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap",
  },
];

Merging Parent and Child Meta

Child route meta merges with parent meta:

// Parent route (dashboard.tsx)
export const meta: MetaFunction = () => [
  { title: "Dashboard — My App" },
];

// Child route (dashboard.analytics.tsx)
export const meta: MetaFunction = ({ parentData }) => {
  const parentMeta = parentData.find(m => m.title);
  return [
    { title: "Analytics — My App" }, // Overrides parent title
    { name: "description", content: "View your analytics data" },
  ];
};

Dynamic Meta with Loader Data

Use loader data in meta:

export const loader = async ({ params }) => {
  const post = await getPost(params.slug);
  return json(post);
};

export const meta: MetaFunction<typeof loader> = ({ data }) => {
  return [
    { title: `${data.title} — Blog` },
    { name: "description", content: data.description },
    { "script:ld+json": {
      "@context": "https://schema.org",
      "@type": "Article",
      headline: data.title,
      datePublished: data.date,
    }},
  ];
};

Common Mistakes

  1. Returning objects instead of arrays: Remix v2 uses arrays of meta objects. { title: "..." } is invalid. Use [{ title: "..." }].
  2. Not using parentData for merged meta: Without accessing parentData, child meta doesn't inherit parent values.
  3. Hardcoding canonical URLs: Canonical URLs should use the full site URL from environment variables, not hardcoded strings.
  4. Forgetting the title in meta array: Each page must have a title tag. Omitting it hurts SEO.
  5. Not adding links for global stylesheets: Global CSS should be linked in root.tsx via links, not imported with JavaScript.

Practice Questions

  1. What does the meta export return? Answer: An array of meta objects, each with title, name, property, or custom attributes for <head> tags.

  2. How do you use loader data in meta? Answer: The MetaFunction receives { data } which contains the loader's return value. Use it for dynamic titles and descriptions.

  3. What is the links export used for? Answer: Adding <link> elements to the <head>, including stylesheets, canonical URLs, favicons, and preconnect hints.

  4. How does child route meta merge with parent meta? Answer: The child's meta array overrides matching parent entries. Access parentData parameter to include parent meta values.

Challenge

Build a blog with per-page meta tags: the blog list has a generic title, individual posts use the post title from loader data, and each post includes Open Graph and JSON-LD structured data.

Mini Project

Create a site-wide SEO system where the root layout provides default meta tags, and each route extends or overrides them with route-specific title, description, and Open Graph images.

FAQ

Can I use the `meta` export for JSON-LD structured data?

: Yes. Use "script:ld+json" key in the meta object to inject JSON-LD schema markup.

How do I add inline styles or scripts?

: Use the links export for stylesheets. For inline scripts, add them directly in root.tsx or use <Scripts />.

Does Remix handle meta tag ordering?

: Yes. Child route meta appears after parent meta in the <head>. Later tags override earlier ones for matching attributes.

Can I use the `meta` export in root.tsx?

: Yes. The root's meta export serves as the default for all pages.

What's Next

Learn about Remix Resources Routes for creating non-page routes that return JSON, files, or other data.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro