Files
claude@clouddev1 09b64cbfb7 feat(website): Open Graph social card
Add a 1200x630 social card (dark bg, monospace, teal database-table
motif, the relplay/RDBMS reveal) shown when pages are shared. Source
SVG in src/assets/og-card.svg, rasterised to public/og-card.png with
sharp. Wire site-wide og:image + twitter summary_large_image tags via
Starlight head, with the absolute relplay.org URL.
2026-06-11 18:59:02 +00:00

82 lines
3.7 KiB
JavaScript

// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import tailwindcss from '@tailwindcss/vite';
// Custom highlight grammar for the playground's simple-mode command language
// (advanced-mode examples use the built-in `sql` grammar). Fence with ```rdbms.
import rdbmsLang, { rdbmsSyntax } from './src/grammars/rdbms.mjs';
// https://astro.build/config
export default defineConfig({
// Production origin (apex domain). Enables the sitemap, canonical URLs, and
// Open Graph `og:url`/`og:image` resolution. A `www` host, if used, should
// 301-redirect here so a single canonical origin is advertised. Local dev is
// unaffected — this only changes *generated absolute* URLs, not where the
// dev/preview server binds.
site: 'https://relplay.org',
// Bind the dev/preview server to IPv4 loopback. Astro/Vite's default
// `localhost` bind resolves to IPv6 `::1` here, which breaks SSH
// `-L 4321:127.0.0.1:4321` tunnels (they target IPv4). Pinning 127.0.0.1
// keeps loopback-only access and makes tunnelling unambiguous.
server: { host: '127.0.0.1' },
integrations: [
starlight({
title: 'RDBMS Playground',
tagline: 'Learn relational databases by doing.',
// Header logo: a database-table glyph with a teal primary-key cell.
// Separate light/dark files so the outline adapts to the theme;
// `replacesTitle: false` keeps the "RDBMS Playground" wordmark beside it.
logo: {
light: './src/assets/relplay-logo-light.svg',
dark: './src/assets/relplay-logo-dark.svg',
replacesTitle: false,
},
// Footer override: Starlight's default footer + a small company/source line.
components: {
Footer: './src/components/Footer.astro',
},
// TODO(Phase B): a header social link to the repo is deliberately omitted
// — the source/issues link lives understated in the footer instead.
customCss: ['./src/styles/global.css'],
// Open Graph / Twitter social card. Starlight emits og:title/url/type
// from `site`, but not an image, so add a single site-wide card.
// Source: src/assets/og-card.svg → public/og-card.png (rasterise with
// sharp; see the SVG header for the one-liner). Absolute URL required
// by scrapers — derived from the `site` origin.
head: [
{ tag: 'meta', attrs: { property: 'og:image', content: 'https://relplay.org/og-card.png' } },
{ tag: 'meta', attrs: { property: 'og:image:width', content: '1200' } },
{ tag: 'meta', attrs: { property: 'og:image:height', content: '630' } },
{
tag: 'meta',
attrs: {
property: 'og:image:alt',
content: 'RDBMS Playground — learn relational databases by doing.',
},
},
{ tag: 'meta', attrs: { name: 'twitter:card', content: 'summary_large_image' } },
{ tag: 'meta', attrs: { name: 'twitter:image', content: 'https://relplay.org/og-card.png' } },
],
// Register the simple-mode command grammar with Expressive Code (Shiki).
expressiveCode: { shiki: { langs: [rdbmsLang, rdbmsSyntax] } },
// Pragmatic structure (ADR-website-001 §7 / website/STYLE.md): Getting
// started, Guides, Reference, Concepts. Autogenerated per directory;
// in-section order is controlled by each page's `sidebar.order`
// frontmatter.
sidebar: [
{ label: 'Getting started', items: [{ autogenerate: { directory: 'getting-started' } }] },
{ label: 'Using the playground', items: [{ autogenerate: { directory: 'using-the-playground' } }] },
{ label: 'Guides', items: [{ autogenerate: { directory: 'guides' } }] },
{ label: 'Reference', items: [{ autogenerate: { directory: 'reference' } }] },
{ label: 'Concepts', items: [{ autogenerate: { directory: 'concepts' } }] },
],
}),
],
vite: {
plugins: [tailwindcss()],
},
});