From 57e8289589d304ac8b251a76e72d3bad4b4201a7 Mon Sep 17 00:00:00 2001 From: 130U Date: Fri, 31 Jul 2026 08:44:03 -0400 Subject: [PATCH 1/3] Modernize site architecture and publishing --- .github/workflows/pages.yml | 46 +- .gitignore | 3 + app/README.md | 31 +- app/components/SiteShell.tsx | 48 +- app/education/page.tsx | 6 +- app/globals.css | 134 +- app/layout.tsx | 54 +- app/lib/content/experience.ts | 174 + app/lib/content/posts.ts | 62 + app/lib/content/routes.ts | 13 + app/lib/content/site.ts | 89 + app/lib/pastExperience.ts | 65 - app/not-found.tsx | 27 + app/now/page.tsx | 8 +- app/page.tsx | 12 +- app/past-experience/[slug]/page.tsx | 42 + .../artificial-intelligence/page.tsx | 10 - .../components/ExperienceDomainPage.tsx | 23 +- app/past-experience/data-science/page.tsx | 10 - app/past-experience/domainRoutes.ts | 27 - .../page.tsx | 15 - app/past-experience/finance/page.tsx | 10 - app/past-experience/page.tsx | 12 +- .../page.tsx | 15 - app/personal-posts/README.md | 27 +- app/personal-posts/[slug]/page.tsx | 77 + .../RobotActionPathsPost.tsx} | 61 +- app/personal-posts/page.tsx | 53 +- app/robots.ts | 15 + app/sitemap.ts | 9 + config/README.md | 6 +- content/README.md | 12 +- next.config.ts | 8 + package-lock.json | 10566 ++++++---------- package.json | 38 +- .../postcss.config.mjs => postcss.config.mjs | 0 public/.nojekyll | 1 + public/assets/brand/og-1774.jpg | Bin 0 -> 273255 bytes .../posts/wam-vla-two-paths-en-1440.webp | Bin 0 -> 166628 bytes .../posts/wam-vla-two-paths-en-720.webp | Bin 0 -> 51728 bytes .../profile/theodore-avatar-warm-384.avif | Bin 0 -> 24386 bytes .../profile/theodore-avatar-warm-384.webp | Bin 0 -> 16264 bytes .../profile/theodore-avatar-warm-768.avif | Bin 0 -> 122005 bytes .../profile/theodore-avatar-warm-768.webp | Bin 0 -> 71276 bytes scripts/README.md | 13 +- scripts/check-published-copy-fixtures.mjs | 40 + scripts/export-static.mjs | 81 - scripts/optimize-images.mjs | 57 + scripts/preview-static.mjs | 48 +- tests/README.md | 36 +- tests/fixtures/accessible-label-baseline.json | 72 + .../accessible-labelledby-baseline.json | 18 + tests/fixtures/content-baseline.json | 1007 ++ tests/fixtures/published-copy/README.md | 33 + tests/rendered-html.test.mjs | 1172 +- types/README.md | 6 +- types/raw-modules.d.ts | 4 - vite.config.ts | 35 - website-maintenance/01-page-file-map.md | 46 +- .../02-repository-structure.md | 111 +- .../03-adding-personal-posts.md | 77 +- website-maintenance/04-release-checklist.md | 57 +- .../05-architecture-decisions.md | 50 + website-maintenance/06-public-assets.md | 18 + website-maintenance/README.md | 42 +- worker/README.md | 5 - worker/index.ts | 46 - 67 files changed, 7077 insertions(+), 7806 deletions(-) create mode 100644 app/lib/content/experience.ts create mode 100644 app/lib/content/posts.ts create mode 100644 app/lib/content/routes.ts create mode 100644 app/lib/content/site.ts delete mode 100644 app/lib/pastExperience.ts create mode 100644 app/not-found.tsx create mode 100644 app/past-experience/[slug]/page.tsx delete mode 100644 app/past-experience/artificial-intelligence/page.tsx delete mode 100644 app/past-experience/data-science/page.tsx delete mode 100644 app/past-experience/domainRoutes.ts delete mode 100644 app/past-experience/environmental-social-and-governance/page.tsx delete mode 100644 app/past-experience/finance/page.tsx delete mode 100644 app/past-experience/stem-academic-competitions-and-training/page.tsx create mode 100644 app/personal-posts/[slug]/page.tsx rename app/personal-posts/{from-vision-and-instructions-to-robot-actions/page.tsx => _articles/RobotActionPathsPost.tsx} (94%) create mode 100644 app/robots.ts create mode 100644 app/sitemap.ts create mode 100644 next.config.ts rename config/postcss.config.mjs => postcss.config.mjs (100%) create mode 100644 public/.nojekyll create mode 100644 public/assets/brand/og-1774.jpg create mode 100644 public/assets/posts/wam-vla-two-paths-en-1440.webp create mode 100644 public/assets/posts/wam-vla-two-paths-en-720.webp create mode 100644 public/assets/profile/theodore-avatar-warm-384.avif create mode 100644 public/assets/profile/theodore-avatar-warm-384.webp create mode 100644 public/assets/profile/theodore-avatar-warm-768.avif create mode 100644 public/assets/profile/theodore-avatar-warm-768.webp create mode 100644 scripts/check-published-copy-fixtures.mjs delete mode 100644 scripts/export-static.mjs create mode 100644 scripts/optimize-images.mjs create mode 100644 tests/fixtures/accessible-label-baseline.json create mode 100644 tests/fixtures/accessible-labelledby-baseline.json create mode 100644 tests/fixtures/content-baseline.json create mode 100644 tests/fixtures/published-copy/README.md delete mode 100644 types/raw-modules.d.ts delete mode 100644 vite.config.ts create mode 100644 website-maintenance/05-architecture-decisions.md create mode 100644 website-maintenance/06-public-assets.md delete mode 100644 worker/README.md delete mode 100644 worker/index.ts diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 46aa213..87417e7 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -1,45 +1,63 @@ -name: Deploy GitHub Pages +name: Validate and deploy GitHub Pages on: + pull_request: + branches: [main] push: branches: [main] workflow_dispatch: permissions: contents: read - pages: write - id-token: write concurrency: - group: pages + group: pages-${{ github.ref }} cancel-in-progress: false jobs: - build-and-deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} + build: runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false - name: Set up Node uses: actions/setup-node@v4 with: node-version: 24 cache: npm + - name: Guard immutable and append-only preservation fixtures + if: github.event_name != 'workflow_dispatch' + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + run: npm run check:published-copy - name: Install dependencies run: npm ci --ignore-scripts - name: Validate and build run: npm run check - - name: Export static pages - run: npm run export:static - - name: Configure Pages - uses: actions/configure-pages@v5 - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v3 + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v4 with: - path: github-pages + path: out + + deploy: + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Configure Pages + uses: actions/configure-pages@v5 - name: Deploy id: deployment uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 235ed14..270fff0 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,9 @@ yarn-error.log* # typescript next-env.d.ts +*.tsbuildinfo + +# legacy and local build artifacts /dist/ /.wrangler/ /outputs/ diff --git a/app/README.md b/app/README.md index 5dbb0c2..af71205 100644 --- a/app/README.md +++ b/app/README.md @@ -1,25 +1,28 @@ # Application Routes -This directory contains every public page and the shared site interface. - -The router requires the filename `page.tsx`; the directory determines the URL. -For a complete page-to-file index, see: - -```text -website-maintenance/01-page-file-map.md -``` +This directory uses the official Next.js App Router. Static pages keep their +bespoke copy beside their markup; repeatable collections are driven by typed, +validated registries. Key routes: - `page.tsx` — Home. - `education/page.tsx` — Education. -- `past-experience/` — Past Experience directory and five domain pages. +- `past-experience/page.tsx` — Past Experience directory. +- `past-experience/[slug]/page.tsx` — all five experience domain pages. - `now/page.tsx` — Current Chapter at `/now/`. -- `personal-posts/` — Personal Posts index and article pages. +- `personal-posts/page.tsx` — Personal Posts index. +- `personal-posts/[slug]/page.tsx` — all article routes. -Shared files: +Shared responsibilities: -- `components/SiteShell.tsx` — navigation, profile sidebar, and footer. +- `components/SiteShell.tsx` — navigation, profile sidebar, footer, and skip link. - `globals.css` — approved visual system and responsive behavior. -- `layout.tsx` — global metadata, fonts, and browser icons. -- `lib/` — source parsing and route-independent logic. +- `layout.tsx` — global metadata, icons, and Person structured data. +- `lib/content/site.ts` — site constants, navigation, and metadata helper. +- `lib/content/experience.ts` — strict archive parser and experience registry. +- `lib/content/posts.ts` — article metadata registry. +- `lib/content/routes.ts` — canonical public routes used by the sitemap. +- `robots.ts`, `sitemap.ts`, and `not-found.tsx` — static discovery and failure pages. + +See `website-maintenance/01-page-file-map.md` for the complete source map. diff --git a/app/components/SiteShell.tsx b/app/components/SiteShell.tsx index 994ae5e..d81b508 100644 --- a/app/components/SiteShell.tsx +++ b/app/components/SiteShell.tsx @@ -1,25 +1,19 @@ import Link from "next/link"; import type { ReactNode } from "react"; - -type ActivePage = "home" | "now" | "education" | "experience" | "posts"; - -const navigation: Array<{ key: ActivePage; label: string; href: string }> = [ - { key: "home", label: "Home", href: "/" }, - { key: "education", label: "Education", href: "/education/" }, - { key: "experience", label: "Past Experience", href: "/past-experience/" }, - { key: "now", label: "Current Chapter", href: "/now/" }, - { key: "posts", label: "Personal Posts", href: "/personal-posts/" }, -]; +import { navigation, type ActivePage } from "../lib/content/site"; export function SiteShell({ active, children, }: { - active: ActivePage; + active?: ActivePage; children: ReactNode; }) { return (
+ + Skip to main content +
@@ -44,15 +38,27 @@ export function SiteShell({ -
{children}
+
+ {children} +