feat: add article tags and image alt text to OG metadata

- Add tags field to ArticleMetadata type (extracted from 't' tags)
- Add imageAlt field to ArticleMetadata type (uses title as fallback)
- Extract 't' tags from article events in fetchArticleMetadataViaRelays
- Generate multiple article:tag meta tags in HTML output
- Add og:image:alt meta tag for better accessibility

This improves SEO and social media previews by including
article categorization tags and image descriptions.
This commit is contained in:
Gigi
2025-11-07 19:39:02 +01:00
parent 4fc4971345
commit 76b9797c41
3 changed files with 23 additions and 2 deletions

View File

@@ -70,6 +70,15 @@ export async function fetchArticleMetadataViaRelays(naddr: string): Promise<Arti
const summary = getArticleSummary(article) || 'Read this article on Boris'
const image = getArticleImage(article) || '/boris-social-1200.png'
// Extract 't' tags (topic tags) from article event
const tags = article.tags
?.filter((tag) => tag[0] === 't' && tag[1])
.map((tag) => tag[1])
.filter((tag) => tag.length > 0) || []
// Generate image alt text (use title as fallback)
const imageAlt = title || 'Article cover image'
let authorName = pointer.pubkey.slice(0, 8) + '...'
if (profileEvents.length > 0) {
const displayName = extractProfileDisplayName(profileEvents[0])
@@ -85,7 +94,9 @@ export async function fetchArticleMetadataViaRelays(naddr: string): Promise<Arti
summary,
image,
author: authorName,
published: article.created_at
published: article.created_at,
tags: tags.length > 0 ? tags : undefined,
imageAlt
}
} catch (err) {
console.error('Failed to fetch article metadata via relays:', err)

View File

@@ -17,6 +17,12 @@ export function generateHtml(naddr: string, meta: ArticleMetadata | null): strin
const description = meta?.summary || 'Your reading list for the Nostr world. A minimal nostr client for bookmark management with highlights.'
const image = meta?.image?.startsWith('http') ? meta.image : `${baseUrl}${meta?.image || '/boris-social-1200.png'}`
const author = meta?.author || 'Boris'
const imageAlt = meta?.imageAlt || title
// Generate article:tag meta tags
const articleTags = meta?.tags && meta.tags.length > 0
? meta.tags.map((tag) => ` <meta property="article:tag" content="${escapeHtml(tag)}" />`).join('\n')
: ''
return `<!doctype html>
<html lang="en">
@@ -39,9 +45,11 @@ export function generateHtml(naddr: string, meta: ArticleMetadata | null): strin
<meta property="og:title" content="${escapeHtml(title)}" />
<meta property="og:description" content="${escapeHtml(description)}" />
<meta property="og:image" content="${escapeHtml(image)}" />
<meta property="og:image:alt" content="${escapeHtml(imageAlt)}" />
<meta property="og:site_name" content="Boris" />
${meta?.published ? `<meta property="article:published_time" content="${new Date(meta.published * 1000).toISOString()}" />` : ''}
${meta?.published ? ` <meta property="article:published_time" content="${new Date(meta.published * 1000).toISOString()}" />` : ''}
<meta property="article:author" content="${escapeHtml(author)}" />
${articleTags}
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />

View File

@@ -25,6 +25,8 @@ export type ArticleMetadata = {
image: string
author: string
published?: number
tags?: string[]
imageAlt?: string
}
export async function getArticleMeta(naddr: string): Promise<ArticleMetadata | null> {