Commit Graph
10 Commits
Author SHA1 Message Date
andwati 12dd32ea4f Polish nav, transitions, layout, SEO, a11y, LaTeX, and Lighthouse CI
Nav bar & layout consistency
- Base.astro's `wide` layout now defaults on for every page (was opt-in),
  fixing the nav bar wrapping differently depending on page width
- Icon buttons for search and theme toggle (magnifying glass, sun/moon),
  replacing the plain "Search" text link and the "◐" glyph
- Search is now a Cmd/Ctrl+K modal over Pagefind (lazy-loaded on first
  open) instead of a separate /search/ page, matching the old site
- Fixed the article page's TOC sitting with unwanted left padding relative
  to the header (grid was center-justified instead of start-justified)

Smooth navigation
- Added Astro's ClientRouter for animated page transitions
- Every page-local script that only ran once at module load (three.js
  hero, minimap, comments, book-spine carousel, scroll-to-top, reading
  progress, theme toggle, Pagefind init) now re-initializes via
  astro:page-load, with AbortController-based cleanup so window/document
  listeners don't accumulate across client-side navigations

Restored from the legacy Zola site
- Reading progress bar (article pages) and scroll-to-top button
- Share buttons (X, Bluesky, LinkedIn, Reddit, HN, email) on writings
- Prev/next post navigation with the old label/title layout
- Utterances comments, wired to andwati/andwati.com with dark/light
  theme sync
- YouTube embeds: any plain <iframe src="...youtube-nocookie.com...">
  is now auto-wrapped in a responsive 16:9 container, gets
  loading="lazy", and emits VideoObject JSON-LD — no shortcode needed
- LaTeX: $inline$ and $$block$$ math renders to static HTML via KaTeX at
  build time (no client-side JS shipped for it)
- Tags page redesigned as a centered, alphabetical tag cloud

Removed the related-posts section per request.

Accessibility & contrast
- --accent (#d1502f) measured 4.0:1 on the light background, just under
  WCAG AA's 4.5:1 for normal text — darkened to #a84025 (5.7:1), plus
  matching light-mode-only fixes for the two hljs syntax colors and the
  tip/warning callout colors that had the same problem in light mode
- Fixed heading-order violations (h1 straight to h3 with nothing at h2)
  across the homepage, writings/portfolio/bookshelf/blogs lists, and tag
  pages — introduced a shared .entry-title class for the h2 list titles
- Fixed inconsistent title-link underline colors: a plain <a> carries its
  own default underline (in its own text color) instead of matching its
  parent heading's accent-colored one — h1/h2/h3 anchors now explicitly
  inherit the heading's decoration
- Bookshelf spine colors are generated per-title from a hash; the
  lightness-based text-color heuristic could still produce sub-4.5:1
  contrast for some hues (e.g. green) — now computes real WCAG contrast
  and adjusts

Performance
- The three.js homepage hero was the single largest main-thread cost
  site-wide (dragging that page's Lighthouse performance score to the low
  80s while every other page scored 95+): three.js is now dynamically
  imported only once the browser is idle (WebGL-support check split into
  its own tiny module so unsupported browsers never fetch it at all), the
  render loop is capped to ~30fps, and hover raycasting only runs on an
  actual pointer move instead of every frame

SEO & structured data
- Self-referential canonical links site-wide (with override support for
  posts first published elsewhere)
- Sitewide WebSite/Person JSON-LD, plus per-article BlogPosting,
  BreadcrumbList, and (when applicable) VideoObject JSON-LD
- robots.txt explicitly welcomes AI/LLM crawlers (GPTBot, ClaudeBot,
  PerplexityBot, Google-Extended, CCBot, etc.) and points at llms.txt
- Added an Atom feed (RSS and JSON Feed already existed)
- Sitemap now sets <lastmod> per entry from its own date/updated
  frontmatter instead of leaving every URL at build time

Analytics & comments infra
- Self-hosted Umami wiring via PUBLIC_UMAMI_SCRIPT_URL/WEBSITE_ID
  (apps/site/.env.example), no-ops until both are set
- sws.toml's CSP updated to allow utteranc.es and analytics.andwati.com —
  without this both were silently blocked in production

Lighthouse CI
- @lhci/cli wired up against the built site (mobile + desktop configs),
  `pnpm run lighthouse`, and a GitHub Actions workflow to run it on every
  push/PR — reporting only for now, no failing thresholds
2026-09-12 20:40:16 +03:00
andwati 27e53993d6 Swap shiki for highlight.js's core build for syntax highlighting
Shiki pulls in a WASM oniguruma engine and bundled theme/grammar JSON
for two full themes; highlight.js's core build plus only the 11
languages content actually uses is much thinner for the same job here.
Token colors now come straight from the design tokens (--accent,
--text-muted, ...) instead of shiki's dual-theme CSS vars, so they
already switch with the site's theme with no extra [data-theme] rules.
2026-09-01 09:20:12 +03:00
andwati 74a7f80b29 Render legacy callout shortcodes, add code syntax highlighting
Converts the note/tip/warning/danger `{% <tag> %}...{% </tag> %}` blocks
the posts→writings migration script left untranslated into styled
.callout markup (toml-content-loader.ts's renderCallouts(), styled in
global.css to match the new design system).

Also wires shiki into the same markdown pipeline for fenced code block
highlighting (github-light/github-dark, switched by the same
[data-theme]/prefers-color-scheme pattern tokens.css already uses).

Also records the Three.js centerpiece's perf budget check in TODO.md:
scene is trivially light (well under 10k triangles, 100+fps uncapped);
the ~130KB gzip payload is three.js core itself, not a tree-shaking gap
(verified named imports change nothing - sideEffects:false already lets
Rollup shake fully), and the script is a deferred module that doesn't
block first paint. No code changes needed there.
2026-09-01 09:14:29 +03:00
andwati c035aca132 Add OG image auto-generation for writings, portfolio, and bookshelf
Replaces the legacy Zola script, which was hard-coded to the retired
"CASE FILE" branding, with scripts/generate-og-images.astro-site.mjs
built on the new design system's dark palette + Fraunces/JetBrains Mono.
Base.astro now renders og:image/twitter:image from a per-page ogImage
prop, wired into the writings and bookshelf detail pages.

Uses static-weight Fraunces/Newsreader font packages rather than the
variable fonts the site ships elsewhere, since satori's opentype.js
parser throws on their fvar table.
2026-09-01 08:59:42 +03:00
andwati 9392d45f53 Build the design system: typography, color tokens, real Base layout
References: pixperk.tech (dark, warm off-white text, serif-italic +
mono mixed typography, personal dashboard modules) and mcyoung.xyz
(meta line with reading time, subtle accent underline on titles).

- src/styles/tokens.css: dark-first color palette with a warm-paper
  light mode (data-theme override + prefers-color-scheme, toggle wins
  either direction), fluid clamp() type scale, spacing/radius scale.
- Fonts: Fraunces (display/headings, italic), Newsreader (body,
  long-form readability), JetBrains Mono (nav/meta/code) — all
  self-hosted via @fontsource, continuing the mono choice already
  used in the legacy OG-image pipeline.
- Base.astro rewritten: real header/nav with active-link state, a
  theme toggle (persisted to localStorage, no-flash inline script),
  footer with social links (ported from zola.toml), replacing the
  scaffold placeholder.
- Reading time: toml-content-loader.ts computes wordCount/
  readingMinutes from the raw body at load time, surfaced in the
  writings list and detail meta line.
- Bug fix: the marked heading renderer was using raw token.text for
  both the visible heading and the TOC, so a heading like
  "**Registers**" rendered literal asterisks instead of bold — now
  renders inline tokens properly and strips markdown for the
  plain-text TOC label/slug.

Verified in-browser (light + dark) across home, a migrated writing
with TOC/headings, bookshelf, and 404.
2026-08-31 08:03:50 +03:00
andwati 2fdd0052b5 Extend llms.txt to all content types; fix a gitignore bug
scripts/generate-llms.astro-site.mjs covers writings, portfolio,
bookshelf, and blogs (unblocked now that site.config.ts exists from
the feeds/meta work), wired into apps/site's build script.

Also fixes .gitignore: the bare `public` pattern (meant to ignore the
Zola build's root-level output directory) was matching at any depth,
so apps/site/public/ and apps/cms/public/ were being silently
excluded from every commit despite `git add` reporting them as
staged for directory adds (the ignore-file warning only surfaces for
an explicitly named path, not a recursive directory add — easy to
miss). Scoped to `/public` so only the root output dir is ignored.
Picks up robots.txt, the Astro scaffold's favicon, llms.txt, and
Strapi's own public/robots.txt, none of which were actually tracked
until now.
2026-08-30 19:18:43 +03:00
andwati 02a7a6197f Add feeds, sitemap, search, tags, and per-post nav/TOC/series/related
- src/site.config.ts: minimal site metadata (title, description,
  base URL, nav, tag descriptions) ported from the legacy zola.toml
  as a placeholder pending real design/copy.
- RSS (@astrojs/rss) and JSON Feed endpoints, sitemap
  (@astrojs/sitemap), robots.txt.
- Base.astro: meta description (site-wide default or per-page
  override via llms_description/description), RSS/JSON feed
  <link rel=alternate>, and a webmention endpoint link (plumbing
  only — needs the domain registered on webmention.io to do
  anything).
- toml-content-loader.ts: marked renderer now assigns heading ids
  and collects them into rendered.metadata.headings, so
  render(entry) exposes headings the same way a built-in Markdown
  loader would.
- Writing detail page: table of contents, prev/next navigation,
  series-nav (uses the existing extra.series/series_index fields),
  and tag-overlap related posts.
- Tags index + per-tag pages, tag links wired in from writing cards.
- Pagefind: indexes the build output as part of `pnpm build`
  (astro build && pagefind --site dist), plus a /search/ page using
  Pagefind's default UI.

Verified: astro check clean, full build succeeds (feeds/sitemap/
pagefind all generate correctly), and manually exercised /search/
(real query, highlighted results) and /tags/ in a browser against
the built site.
2026-08-30 19:04:25 +03:00
andwati 16c8dff5d5 Wire Astro content collections to the shared content/ directory
Adds a custom Astro loader that reads the Zola-style TOML frontmatter
(+++ ... +++) directly, so content/ stays the single source of truth
with no YAML conversion step. Defines writings/portfolio/bookshelf/
blogs collections and basic list/detail pages for each, rendering the
seed entries end-to-end (verified in-browser via `pnpm --filter site
dev`). This is the first runnable MVP: home, writings list + post
detail, portfolio, bookshelf (books and papers), and curated blogs
all render from real content/ files.
2026-08-30 18:14:34 +03:00
andwati cae62d4a66 Apply Biome formatting across the workspace
Fixes the formatting deltas from the initial Astro/Strapi scaffold
and brings the legacy generate-og-images/generate-llms/validate-post
scripts in line with Biome's style. No behavioral changes.
2026-08-30 17:59:30 +03:00
andwati 80e1d55ea1 Scaffold Astro/Strapi monorepo for the site rebuild
Set up a pnpm workspace with apps/site (Astro) and apps/cms (Strapi,
SQLite-backed) as the foundation for the new digital-legacy site.
Switches package management to pnpm and adds Biome for linting/
formatting, replacing npm/no-linter setup. Existing Zola site stays
in place for now and will be migrated/removed progressively.
2026-08-30 17:56:36 +03:00