Remix Links and Meta — SEO and Head Management
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" },
];
};
Links Export
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
- Returning objects instead of arrays: Remix v2 uses arrays of meta objects.
{ title: "..." }is invalid. Use[{ title: "..." }]. - Not using
parentDatafor merged meta: Without accessingparentData, child meta doesn't inherit parent values. - Hardcoding canonical URLs: Canonical URLs should use the full site URL from environment variables, not hardcoded strings.
- Forgetting the
titlein meta array: Each page must have a title tag. Omitting it hurts SEO. - Not adding
linksfor global stylesheets: Global CSS should be linked inroot.tsxvialinks, not imported with JavaScript.
Practice Questions
What does the
metaexport return? Answer: An array of meta objects, each withtitle,name,property, or custom attributes for<head>tags.How do you use loader data in meta? Answer: The
MetaFunctionreceives{ data }which contains the loader's return value. Use it for dynamic titles and descriptions.What is the
linksexport used for? Answer: Adding<link>elements to the<head>, including stylesheets, canonical URLs, favicons, and preconnect hints.How does child route meta merge with parent meta? Answer: The child's meta array overrides matching parent entries. Access
parentDataparameter 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
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