Open Graph Plugin

Purpose

Generates Open Graph (og:*), Twitter Card (twitter:*), and JSON-LD structured data for every content file and rendered page. The most complex plugin in the ecosystem, with schema-specific structured data for 10+ page types.

Location

  • Package: @shevky/plugin-open-graph
  • Main: plugin-open-graph/main.js
  • Sub-modules: plugin-open-graph/src/ (pipeline, meta, helpers, constants, structured/)
  • Runtime name: shevky-open-graph

Lifecycle Hooks

HookImplementedPurpose
content:readyBuild metadata for all content files in bulk
page:metaBuild/update metadata per page at render time

This is the only plugin implementing two hooks and the only one using page:meta.

How It Works

content:ready Hook

Iterates all ctx.contentFiles, for each valid file:

  1. Extracts front matter target.
  2. Builds page metadata (canonical URL, OG title/description/image, Twitter card, JSON-LD).
  3. Mutates the front matter object to inject og, twitter, structuredData, and pageMeta fields.

page:meta Hook

For individual pages during rendering:

  1. Reads ctx.frontMatter and ctx.derivedFrontMatter.
  2. Builds page metadata.
  3. Calls ctx.setPageMeta(meta) to provide the render engine with SEO data.

Schema-Specific JSON-LD

Uses a strategy pattern in src/structured/index.js to dispatch by schema type:

Schema TypeJSON-LD Typeog:type
postArticlearticle
job-postJobPostingwebsite
job-listingItemList + JobPostingwebsite
homeWebSite + CollectionPagewebsite
aboutAboutPagewebsite
contactContactPagewebsite
help / faqFAQPagewebsite
pressWebPagewebsite
not-foundWebPage (noindex)website
collectionCollectionPagewebsite
defaultWebPagewebsite

Configuration

Read from pluginConfigs["shevky-open-graph"]:

KeyTypeDefaultDescription
twitterSitestring""Twitter @username for twitter:site
defaultTwitterCardstring"summary_large_image"Default card type
defaultImagestring""Fallback OG/Twitter image
forcebooleanfalseOverwrite existing OG values
siteNamestring""og:site_name override
publisherTypestring"person""person" or "organization"
exposePageMetabooleantrueExpose pageMeta on front matter
enableSearchActionboolean|nullnullAdd SearchAction to WebSite schema
contactobject|nullnullContact info for ContactPoint

Additional keys for advanced schema: jobCategoryTokens, jobUrlTokens, localityCountryTokens, faqItemsPaths, newsItemsPaths, questionCount, jobValidThroughDays, searchActionTarget, searchActionQueryInput.

Dependencies

  • @shevky/base - plugin, format, i18n
  • No external dependencies.

Risks and Limitations

  • Largest plugin: ~3000+ lines across all files. High complexity and maintenance burden.
  • Mutates shared state: Directly writes to content file front matter objects, affecting all subsequent plugins and the render pipeline.
  • Duplicated URL logic: Contains its own canonical URL resolution rather than delegating to MetaEngine.
  • Module-level mutable state: Maintains runtimeI18n, runtimeCollections, and runtimePluginConfig variables that must be refreshed per invocation.
  • Heuristic schema detection: Can produce false positives for unusual content metadata patterns. (Inferred from rule density in helpers.js.)

Related