Meta Tags, SEO & Social Sharing Design

Date: 2026-03-01 Branch: feature-meta

Goal

Add comprehensive meta tags, OpenGraph, Twitter Cards, structured data, and SEO infrastructure so thalida.com shows up well in search results and looks great when links are shared on social media.

Approach

Port the v-2025 branch’s meta/SEO setup into the current codebase with improvements:

  • Dedicated <SEO> component (not inline in BaseLayout)
  • Per-page dynamic OG images (cover images when available)
  • Proper canonical URLs (not hardcoded)
  • Dynamic og:type (article for posts, website for pages)

Architecture

<SEO> Component

File: app/src/components/SEO/SEO.astro

Props:

interface Props {
title?: string; // Page title (default: "thalida")
description?: string; // Meta description
image?: string; // OG image URL (default: /card-512x512.png)
type?: "website" | "article";
url?: string; // Canonical URL (auto-derived from Astro.url)
publishedOn?: Date; // article:published_time
updatedOn?: Date; // article:modified_time
tags?: string[]; // article:tag
noindex?: boolean; // Opt-out of indexing
}

Renders:

  • <meta name="description">
  • <meta name="author" content="Thalida Noel">
  • <meta name="theme-color" content="#1be48c">
  • <link rel="canonical">
  • OpenGraph: og:title, og:description, og:image, og:type, og:url, og:site_name
  • Twitter: twitter:card (summary_large_image), twitter:title, twitter:description, twitter:image, twitter:site (@thalida), twitter:creator (@thalida)
  • For articles: article:published_time, article:modified_time, article:tag
  • Favicon links: icon, apple-touch-icon

Default description:

“Thalida Noel’s corner of the internet since 2007 — projects, guides, experiments, and the occasional recipe from a creative technologist in New York.”

BaseLayout Changes

File: app/src/layouts/BaseLayout/BaseLayout.astro

Extend Props:

interface Props {
title?: string;
activePage?: string;
activeCollection?: string;
description?: string;
ogImage?: string;
ogType?: "website" | "article";
publishedOn?: Date;
updatedOn?: Date;
tags?: string[];
noindex?: boolean;
}

Render <SEO> inside <head>, before existing <slot name="head" />.

Per-Page Metadata

PagetitledescriptionogImageogType
Homepage /thalidaSite defaultDefault cardwebsite
About /aboutabout · thalidaSite defaultDefault cardwebsite
Collection /projectsProjects · thalidacollectionMeta[name].descriptionDefault cardwebsite
Post /projects/post/xyzPost Title · thalidaentry.data.descriptionCover image or defaultarticle
Login/Logoutlogin · thalidawebsite + noindex

For post cover images: resolve Astro ImageMetadata.src to absolute URL using Astro.site.

Static Assets (ported from v-2025)

Into app/public/:

  • favicon.ico, favicon.svg, favicon-16x16.png, favicon-32x32.png
  • apple-touch-icon.png
  • android-chrome-192x192.png, android-chrome-512x512.png
  • card-512x512.png (default OG image)

New files:

  • app/public/robots.txtUser-agent: * Allow: / Sitemap: https://thalida.com/sitemap-index.xml
  • app/public/site.webmanifest — name, short_name, icons, theme_color, background_color

Astro Config Changes

File: app/astro.config.mjs

Add @astrojs/sitemap integration for automatic sitemap generation.

JSON-LD Structured Data

Person schema (about page only):

  • Name, alternateName, url, image, jobTitle, description
  • worksFor, alumniOf, sameAs, knowsAbout, address

Article schema (all non-recipe posts):

  • headline, description, keywords, articleSection
  • author (Person), publisher (Organization)
  • datePublished, dateModified

Recipe schema (unchanged — already implemented).

Files Changed

FileAction
app/src/components/SEO/SEO.astroCreate
app/src/layouts/BaseLayout/BaseLayout.astroModify — add SEO props, render <SEO>
app/src/pages/index.astroModify — pass description
app/src/pages/about.astroModify — add Person JSON-LD
app/src/pages/[collection]/[...page].astroModify — pass collection description
app/src/pages/[collection]/post/[...id].astroModify — pass post metadata, add Article JSON-LD
app/src/pages/[collection]/[category]/[...page].astroModify — pass description
app/src/pages/login.astroModify — add noindex
app/src/pages/logout.astroModify — add noindex
app/astro.config.mjsModify — add @astrojs/sitemap
app/public/robots.txtCreate
app/public/site.webmanifestCreate
app/public/favicon.*Create (ported from v-2025)
app/public/card-512x512.pngCreate (ported from v-2025)