SEO
Global meta tags, Open Graph, Twitter Cards, robots.txt, and per-page metadata.
SEO
Global SEO defaults (meta tags, Open Graph, Twitter Cards, robots.txt) plus a <Metadata> component for per-page overrides.
Installation
bun add @manicjs/seoQuick Start
1. Configure Global Defaults
// manic.config.ts
import { } from 'manicjs/config';
import { } from '@manicjs/seo';
export default ({
: [
({
: 'https://example.com',
: 'My App',
: 'Build amazing apps with Manic',
}),
],
});2. Override Per Page
// app/routes/about.tsx
import { } from '@manicjs/seo/metadata';
export default function () {
return (
<>
<
="About Us"
="Learn more about our company"
="/images/about-og.png"
/>
<>About Us</>
</>
);
}The <Metadata> component overrides the global defaults for that page. When the user navigates away, the previous values are restored automatically.
Global Options
Prop
Type
TwitterConfig
Prop
Type
OpenGraphConfig
Prop
Type
RobotRule
Prop
Type
ContentSignals
Prop
Type
Full Example
// manic.config.ts
import { } from 'manicjs/config';
import { } from '@manicjs/seo';
export default ({
: [
({
: 'https://example.com',
: 'My App',
: 'Build amazing apps with Manic',
: 'John Doe',
: {
: 'summary_large_image',
: '@myapp',
: '@johndoe',
},
: {
: 'website',
: 'en_US',
: 'https://example.com/og.png',
: 'My App',
},
: [
{ : '*', : ['/'], : ['/admin'] },
],
: {
'ai-train': 'no',
: 'yes',
},
}),
],
});Generated Output
The plugin generates:
Meta Tags (injected into <head>)
<meta name="title" content="My App">
<meta name="description" content="Build amazing apps with Manic">
<meta name="author" content="John Doe">
<!-- Open Graph -->
<meta property="og:title" content="My App">
<meta property="og:description" content="Build amazing apps with Manic">
<meta property="og:url" content="https://example.com">
<meta property="og:type" content="website">
<meta property="og:image" content="https://example.com/og.png">
<meta property="og:site_name" content="My App">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@myapp">
<meta name="twitter:title" content="My App">
<meta name="twitter:description" content="Build amazing apps with Manic">robots.txt
User-agent: *
Allow: /
Disallow: /admin
Sitemap: https://example.com/sitemap.xml
Content-Signal: ai-train=no, search=yesPer-Page Metadata
The <Metadata> component lets you override global SEO defaults on individual pages. It renders nothing visible — it manages <head> tags via side effects.
import { } from '@manicjs/seo/metadata';Props
Prop
Type
Usage Examples
Static Metadata
// app/routes/about.tsx
import { } from '@manicjs/seo/metadata';
export default function () {
return (
<>
<
="About Us"
="Learn more about our company"
="https://example.com/about"
/>
<>About Us</>
</>
);
}Dynamic Metadata
Use variables and state to set metadata dynamically:
// app/routes/blog/[slug].tsx
import { } from '@manicjs/seo/metadata';
import { } from 'manicjs';
const : <string, { : string; : string; : string }> = {
'hello-world': { : 'Hello World', : 'My first post', : '/images/hello.png' },
'react-tips': { : 'React Tips', : 'Useful React patterns', : '/images/react.png' },
};
export default function () {
const { } = ();
const = [.];
if (!) return <>Post not found</>;
return (
<>
<
={.}
={.}
={.}
="article"
/>
<>
<>{.}</>
<>{.}</>
</>
</>
);
}With Fetched Data
import { } from '@manicjs/seo/metadata';
import { , } from 'react';
export default function () {
const [, ] = <{ : string; : string; : string } | null>(null);
(() => {
('/api/product/1')
.( => .())
.(() => ( as { : string; : string; : string }));
}, []);
return (
<>
{ && (
<
={.}
={.}
={.}
/>
)}
<>{?. ?? 'Loading...'}</>
</>
);
}How It Works
- On mount,
<Metadata>updates existing<meta>/<link>tags or creates new ones in<head> - It saves the previous values of any tags it modifies
- On unmount (when navigating away), it restores the original values — so global SEO defaults come back automatically
- Tags created by
<Metadata>that didn't exist before are removed on cleanup
Integration with Sitemap
Works with @manicjs/sitemap for complete SEO:
import { } from 'manicjs/config';
import { } from '@manicjs/seo';
import { } from '@manicjs/sitemap';
export default ({
: [
({
: 'https://example.com',
: 'My App',
}),
({
: 'https://example.com',
}),
],
});When autoSitemap is true (the default), the SEO plugin automatically adds /sitemap.xml to robots.txt and emits a Link header for sitemap discovery.