Default SEO vs Route SEO

Hi everyone I'm facing an issue where my DEFAULT SEO overrides the ROUTE SEO. I created two components (on the thread): - the default.tsx where I import on app.tsx; - the page.tsx where I import on each route. But, when I see the meta tags, they are from the default.tsx instead of the page.tsx. Any way to keep the default and override it on the routes?
3 Replies
Daniel Sousa @TutoDS
import { Link, Meta, Title } from '@solidjs/meta';
import { createAsync } from '@solidjs/router';
import { Show } from 'solid-js';

function DefaultSeo() {
const seoSettings = createAsync(() => getSeoSettings(), { deferStream: true });

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />

{/* Favicon */}
<Link rel="icon" href="/logo.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>{seo.title}</Title>

<Show when={seo.description} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta property="og:title" content={seo.title} />
<Meta property="og:description" content={seo.description} />

<Show when={seo.thumbnail} keyed={true}>
{(thumbnail) => (
<Meta
property="og:image"
content={urlFor(thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
)}
</Show>
</>
)}
</Show>
</>
);
}

export { DefaultSeo };
import { Link, Meta, Title } from '@solidjs/meta';
import { createAsync } from '@solidjs/router';
import { Show } from 'solid-js';

function DefaultSeo() {
const seoSettings = createAsync(() => getSeoSettings(), { deferStream: true });

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />

{/* Favicon */}
<Link rel="icon" href="/logo.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>{seo.title}</Title>

<Show when={seo.description} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta property="og:title" content={seo.title} />
<Meta property="og:description" content={seo.description} />

<Show when={seo.thumbnail} keyed={true}>
{(thumbnail) => (
<Meta
property="og:image"
content={urlFor(thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
)}
</Show>
</>
)}
</Show>
</>
);
}

export { DefaultSeo };
import { Link, Meta, Title } from '@solidjs/meta';
import { createAsync } from '@solidjs/router';
import { Show } from 'solid-js';

function DefaultSeo() {
const seoSettings = createAsync(() => getSeoSettings(), { deferStream: true });

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />

{/* Favicon */}
<Link rel="icon" href="/logo.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>{seo.title}</Title>

<Show when={seo.description} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta property="og:title" content={seo.title} />
<Meta property="og:description" content={seo.description} />

<Show when={seo.thumbnail} keyed={true}>
{(thumbnail) => (
<Meta
property="og:image"
content={urlFor(thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
)}
</Show>
</>
)}
</Show>
</>
);
}

export { DefaultSeo };
import { Link, Meta, Title } from '@solidjs/meta';
import { createAsync } from '@solidjs/router';
import { Show } from 'solid-js';

function DefaultSeo() {
const seoSettings = createAsync(() => getSeoSettings(), { deferStream: true });

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />

{/* Favicon */}
<Link rel="icon" href="/logo.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>{seo.title}</Title>

<Show when={seo.description} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta property="og:title" content={seo.title} />
<Meta property="og:description" content={seo.description} />

<Show when={seo.thumbnail} keyed={true}>
{(thumbnail) => (
<Meta
property="og:image"
content={urlFor(thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
)}
</Show>
</>
)}
</Show>
</>
);
}

export { DefaultSeo };
And the usage:
app.tsx
<Router
preload={true}
root={(props) => (
<Suspense fallback={<LoadingScreen />}>
<MetaProvider>
<DefaultSeo />
<Header mode="solid" />

{props.children}

<CtaSection />

<Footer />
</MetaProvider>
</Suspense>
)}
>
<FileRoutes />
</Router>
<Router
preload={true}
root={(props) => (
<Suspense fallback={<LoadingScreen />}>
<MetaProvider>
<DefaultSeo />
<Header mode="solid" />

{props.children}

<CtaSection />

<Footer />
</MetaProvider>
</Suspense>
)}
>
<FileRoutes />
</Router>
routes/projects/[slug.tsx]
<Show when={data()} keyed={true}>
{(project) => (
<>
<PageSeo
title={project.title}
keywords={[
project.title.toLowerCase(),
...project.services.map((service) => service.title.toLowerCase()),
]}
description={
project.description
? getTruncatedStringWithEllipsis(project.description)
: undefined
}
image={urlFor(project.thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
...
)}
</Show>
<Show when={data()} keyed={true}>
{(project) => (
<>
<PageSeo
title={project.title}
keywords={[
project.title.toLowerCase(),
...project.services.map((service) => service.title.toLowerCase()),
]}
description={
project.description
? getTruncatedStringWithEllipsis(project.description)
: undefined
}
image={urlFor(project.thumbnail)
.width(800)
.height(600)
.auto('format')
.url()}
/>
...
)}
</Show>
Any suggestion? I change everything to PageSeo and use it with the title as optional
Adam Goldstein
I experienced what I think was a similar issue but kicked the can down the road, iirc it seemed like <Title> would override correctly but the other meta tags wouldn't (my memory could be failing me though). I thought about a solution like wrapping the Router in a context provider, and having a custom Meta wrapper component with a "default" boolean or "priority" integer prop which configures which meta component overrides which, then some whacky state setting in that context when the wrapper mounts (with onCleanup to reset it) so only the non-default/highest priority wrapped Meta children get rendered. If you end up implenting some solution, I'd definitely appreciate it if you shared it, I'll do the same if I get around to that first
Daniel Sousa @TutoDS
I start using only one component and need to put it in every page, didn’t found a better solution 😦 Hi everyone I'm facing a strange issue I'm using the component PageSeo everywhere, but isn't working The seo is from the previous page unitl I refresh the page
Want results from more Discord servers?
Add your server