Add page meta tags for search and link previews
This commit is contained in:
1 parent
411fb03c22
commit
fe60a4443d
6 files changed
+94
-17
No files matched your search
@@ -1,19 +1,30 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
|
import { page } from '$app/state';
|
||||||
import { profile } from '#lib/content';
|
import { profile } from '#lib/content';
|
||||||
|
import { findSitePage } from '#lib/site/pages';
|
||||||
|
import PageMeta, { type PageMetaOptions } from './PageMeta.svelte';
|
||||||
|
|
||||||
let { command, title, subtitle, children }: { command: string; title?: string; subtitle?: string; children?: Snippet } =
|
let {
|
||||||
$props();
|
command,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
description,
|
||||||
|
meta,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
command: string;
|
||||||
|
title?: string;
|
||||||
|
subtitle?: string;
|
||||||
|
description?: string;
|
||||||
|
meta?: PageMetaOptions;
|
||||||
|
children?: Snippet;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
const metaDescription = $derived(description ?? subtitle ?? findSitePage(page.url.pathname)?.description);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<PageMeta {title} description={metaDescription} {...meta} />
|
||||||
{#if title}
|
|
||||||
<title>{title} | {profile.displayName}</title>
|
|
||||||
{/if}
|
|
||||||
{#if subtitle}
|
|
||||||
<meta name="description" content={subtitle} />
|
|
||||||
{/if}
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<div class="command">
|
<div class="command">
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<script lang="ts" module>
|
||||||
|
export type PageMetaOptions = {
|
||||||
|
image?: string;
|
||||||
|
type?: 'website' | 'article' | 'profile';
|
||||||
|
publishedTime?: string;
|
||||||
|
tags?: string[];
|
||||||
|
noIndex?: boolean;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { page } from '$app/state';
|
||||||
|
import { profile } from '#lib/content';
|
||||||
|
|
||||||
|
let {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
image,
|
||||||
|
type = 'website',
|
||||||
|
publishedTime,
|
||||||
|
tags = [],
|
||||||
|
noIndex = false
|
||||||
|
}: PageMetaOptions & { title?: string; description?: string } = $props();
|
||||||
|
|
||||||
|
const fullTitle = $derived(title ? `${title} | ${profile.displayName}` : `${profile.displayName} | Portfolio`);
|
||||||
|
const fullDescription = $derived(description ?? `${profile.title} - ${profile.bio}`);
|
||||||
|
const pageUrl = $derived(`${page.url.origin}${page.url.pathname}`);
|
||||||
|
const imageUrl = $derived(new URL(image ?? profile.photo ?? profile.avatar, page.url.origin).href);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{fullTitle}</title>
|
||||||
|
<meta name="description" content={fullDescription} />
|
||||||
|
<link rel="canonical" href={pageUrl} />
|
||||||
|
{#if noIndex}
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<meta property="og:site_name" content="{profile.displayName}'s Desktop" />
|
||||||
|
<meta property="og:title" content={fullTitle} />
|
||||||
|
<meta property="og:description" content={fullDescription} />
|
||||||
|
<meta property="og:url" content={pageUrl} />
|
||||||
|
<meta property="og:type" content={type} />
|
||||||
|
<meta property="og:image" content={imageUrl} />
|
||||||
|
<meta property="og:image:alt" content={profile.displayName} />
|
||||||
|
|
||||||
|
{#if type === 'article' && publishedTime}
|
||||||
|
<meta property="article:published_time" content={publishedTime} />
|
||||||
|
<meta property="article:author" content={profile.name} />
|
||||||
|
{#each tags as tag (tag)}
|
||||||
|
<meta property="article:tag" content={tag} />
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{#if type === 'profile'}
|
||||||
|
<meta property="profile:username" content={profile.username} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary" />
|
||||||
|
<meta name="twitter:title" content={fullTitle} />
|
||||||
|
<meta name="twitter:description" content={fullDescription} />
|
||||||
|
<meta name="twitter:image" content={imageUrl} />
|
||||||
|
</svelte:head>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<PageHeader command="curl {page.url.pathname}" title="Error {status}" />
|
<PageHeader command="curl {page.url.pathname}" title="Error {status}" meta={{ noIndex: true }} />
|
||||||
|
|
||||||
<pre class="ascii" class:server-error={status >= 500}>{asciiDigits.join('\n')}</pre>
|
<pre class="ascii" class:server-error={status >= 500}>{asciiDigits.join('\n')}</pre>
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
{@html themeStyleTag}
|
{@html themeStyleTag}
|
||||||
<link rel="icon" href="/favicon.png" />
|
<link rel="icon" href="/favicon.png" />
|
||||||
<meta name="author" content={profile.displayName} />
|
<meta name="author" content={profile.displayName} />
|
||||||
|
<link rel="apple-touch-icon" href="/favicon.png" />
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="{profile.displayName}'s Blog" href="/blog/rss.xml" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<svelte:window onkeydown={(event) => handleKeybind(event, openWindowIds)} />
|
<svelte:window onkeydown={(event) => handleKeybind(event, openWindowIds)} />
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { profile } from '#lib/content';
|
import PageMeta from '#lib/components/ui/PageMeta.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<PageMeta type="profile" />
|
||||||
<title>{profile.displayName} | Portfolio</title>
|
|
||||||
<meta name="description" content="{profile.title} - {profile.bio}" />
|
|
||||||
</svelte:head>
|
|
||||||
@@ -9,7 +9,12 @@
|
|||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<article class="article">
|
<article class="article">
|
||||||
<PageHeader command="cat ~/blog/{data.post.slug}.md" title={data.post.title} subtitle={data.post.excerpt} />
|
<PageHeader
|
||||||
|
command="cat ~/blog/{data.post.slug}.md"
|
||||||
|
title={data.post.title}
|
||||||
|
subtitle={data.post.excerpt}
|
||||||
|
meta={{ type: 'article', publishedTime: data.post.date, tags: data.post.tags }}
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<a href="/blog">< back to blog</a>
|
<a href="/blog">< back to blog</a>
|
||||||
|
|||||||
Reference in new issue
Block a user