Start the rebuild: note schema, vault kit and data migration

Phase 1 of the functional design plan.

- Move the old site into legacy/, unchanged, for reference. It still
  builds from there until cutover.
- Add packages/schema: the one definition of all 20 note types, with
  field titles and descriptions, note and vault checks, and JSON Schema
  export so later editing tools and the MCP server share it.
- Add vault-kit: Obsidian templates generated from the schema, and the
  Site guide for 24.01_PersonalWebsite.
- Add tools/migrate: turns the legacy JSON, collections, store data and
  page text into 545 Site folder notes and 84 images, and checks the
  result with the schema.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
Claude
2026-10-11 18:40:55 +00:00
parent 4ded4b277b
commit a2f723ca2d
324 changed files with 11538 additions and 7556 deletions
@@ -0,0 +1,57 @@
---
/**
* InterestCard.astro
* ---------------------------------------------------------------------------
* Generic highlight card used across interest pages (the spec's "Highlights
* (Card Grid)" sections). Each card: an mdi icon, a bold title, and a body.
* Spec emojis in the highlight tables are mapped to mdi icon names at the call
* site.
*
* Optional `currently` prop restyles the card as a "what's active now" item
* with a pulse dot, matching the spec's "Currently" sections.
*/
import Icon from '@components/Icon.astro';
interface Props {
icon: string;
title: string;
/** Optional small status pill text, e.g. "Complete", "Reading". */
status?: string;
currently?: boolean;
class?: string;
}
const { icon, title, status, currently = false, class: className = '' } = Astro.props;
---
<article
class:list={[
'card card-interactive flex h-full flex-col gap-3',
className,
]}
>
<div class="flex items-center justify-between gap-3">
<span
class="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-xl"
style={currently
? 'background: color-mix(in srgb, var(--color-accent) 20%, transparent); color: var(--color-accent);'
: 'background: color-mix(in srgb, var(--color-secondary) 18%, transparent); color: var(--color-secondary);'}
aria-hidden="true"
>
<Icon name={icon} class="h-6 w-6" />
</span>
{currently && (
<span class="inline-flex items-center gap-1.5 font-eyebrow text-[0.65rem] uppercase tracking-[0.18em]" style="color: var(--color-accent);">
<span class="h-2 w-2 rounded-full animate-pulse-glow" style="background: var(--color-accent);"></span>
Active
</span>
)}
{status && !currently && (
<span class="pill">{status}</span>
)}
</div>
<h3 class="font-display text-lg" style="color: var(--color-text);">{title}</h3>
<div class="grow text-sm leading-relaxed" style="color: var(--color-text-muted);">
<slot />
</div>
</article>