Skip to content

feat: redesign the home page with different design and color#32

Closed
dineshbyte wants to merge 35 commits into
developfrom
poc/astro-migration
Closed

feat: redesign the home page with different design and color#32
dineshbyte wants to merge 35 commits into
developfrom
poc/astro-migration

Conversation

@dineshbyte

Copy link
Copy Markdown
Owner

No description provided.

… lesson

Demonstrates the fix for "fix one page, break all": every duplicated chrome
element (the whole <head>, theme scripts, analytics include, hubbar, masthead,
topic chips, feedback widget, closing endnote, quiz JS) moves into two shared
layouts. A lesson page is now just a schema-validated `meta` object plus its
bespoke body — change the masthead once and every lesson updates.

- astro-poc/ is isolated (its own package.json) so the existing CommonJS
  scripts/*.js keep working; builds to ../dist, never docs/.
- build.format:'file' + site/base preserve the exact .html URLs and canonical/
  OG tags, so the GitHub Pages "main -> /docs" deploy model is unchanged.
- src/schema/lesson.ts is the lesson contract; bad/missing metadata is a build
  error, replacing the hand-rolled checks the inject-*.py scripts patch in.

Build instructions and the migration plan are in README-ASTRO-POC.md.
npm is blocked in the authoring sandbox, so the `npm install && npm run build`
verification step runs on the maintainer's machine.
- switch the POC to pnpm; add Prettier with prettier-plugin-astro (tabWidth 4,
  matching .editorconfig) plus `format` / `format:check` scripts
- .gitignore: anchor the EPUB reader's local-only /package.json and
  /pnpm-lock.yaml to the repo root so subdirectory manifests (astro-poc/) track
  normally — removes the broad package.json/lock ignores and the negation hack,
  without exposing the local-only reader files
…-LD), Sources, Rehearse, Steps; Quiz id optional
The Engineering Vault site now builds end-to-end under Astro: 49 pages (the hub
+ 48 teaching pages), output to dist/, faithful to the live design. Deploy model
is unchanged (static HTML → GitHub Pages main → /docs once outDir is flipped).

Hub (src/pages/index.astro + components):
- The 15 hardcoded track cards become ONE typed `tracks` source
  (src/data/tracks.ts, Zod-validated) that feeds the grid, hero count, filter
  counts, search index, no-results catalog and card sheet — no more drift across
  5 hand-maintained copies.
- Chrome → components: SiteHeader, Hero, WhatIsBand, FilterChips, TrackCard,
  TrackGrid, SearchResults, CardSheet, SiteFooter + shared atoms (ThemeToggle,
  SocialLinks, GithubStar). The hub client JS is ported verbatim (search, filter,
  progress->Continue, card sheet, NEW pill); SEARCH_INDEX/CARD_DETAIL derived
  from `tracks`. Fixed the progress_reset double-fire; dropped the pinch-zoom-
  blocking viewport.

Lessons (src/content/lessons/**.mdx + [...slug] route):
- 48 teaching pages → an MDX content collection with schema-validated frontmatter
  (quiz/interview/sources/mc/steps), rendered through LessonLayout via a route
  that preserves the exact .html URLs.
- Recurring widgets are shared components (Quiz/Interview/Sources/Rehearse/Steps/
  MemoryCheck); bespoke SVGs are co-located figure components; the FAQ JSON-LD
  derives from the interview array (can't drift).
- Per-page inline CSS consolidated into lesson.css (#main-scoped); two heavily
  bespoke lessons keep co-located _*.css imports.

Tooling / safety net:
- scripts/check-hub-hooks.js asserts all 19 analytics + ARIA hooks on the built
  hub (PASS — preserves GA4 events with no CI gap).
- astro-poc/scripts/check-mdx.mjs + check-frontmatter.mjs validate every lesson's
  MDX body and YAML frontmatter (48/48 each).
The hub search index is now generated at build from the `lessons` content
collection (one source), restoring deep full-text search that the title+blurb-
only inline derivation had dropped.

- New prerendered endpoint src/pages/assets/search-index.js.ts emits
  window.SEARCH_INDEX as /assets/search-index.js. Each lesson entry's searchable
  `x` is the lowercased title + chips + quiz questions + interview Q&A + sources
  + the stripped MDX body prose (imports/JSX/HTML/entities/markdown removed).
- index.astro: dropped the inline SEARCH_INDEX derivation; loads the endpoint via
  a plain inline-src <script> before the IIFE (CARD_DETAIL stays inline). Deleted
  the stale prebuilt public/assets/search-index.js (collided with the route).
- 83 entries: 48 full-text lessons + 35 track reference pills. Verified a
  body-only phrase ("exaggerates presence") now matches; entry shape {t,u,g,k,x,c}
  unchanged so the ported run() search is untouched.

Scope: the 11 interview-bank pages + reference/glossary pages aren't in the
`lessons` collection yet (not migrated), so they're not indexed — same coverage
as the prior Astro derivation. Build green (49 pages), hub-hooks PASS (19),
check-mdx + check-frontmatter 48/48.
…g <Interview>); BaseLayout extraCss prop; [...slug] route multiplexes collections — 60 pages build green
…ayout, 3 CSS skins) — 70 pages build green; route multiplexes lessons+interview+reference
…ons (retires pandoc build-reference-pages.py); no-dep rehype heading-id plugin gives exact anchor parity — 90 pages build green
…thored site

`astro build` (outDir ../docs, emptyOutDir, build.format:'file') now GENERATES the
published site into docs/; GitHub Pages serves it unchanged (main -> /docs). Full
parity: all 96 URLs byte-identical, 0 real broken internal links, hub analytics/ARIA
hooks intact (19/19), search index 94 entries incl. the 11 interview banks.

Removed from docs/ (now generated, or sourced inside the Astro project):
- hand-authored .html pages -> regenerated by Astro from src/content + components.
- GLOSSARY/RESOURCES/README .md -> source of truth is now src/content/.
- EPUB book build sources (docs/*/epub/**) -> EPUB generation is retired.
Per-track diagram PNGs were recovered into public/*/diagrams/ so Astro re-emits them
at the same URLs (the deep-dive/book pages reference them).

Carried into the Astro project: robots.txt + sitemap.xml (public/); the interview
banks folded into the search-index endpoint.

Kept LOCAL-ONLY (recovered to notes/, gitignored): per-track MISSION.md / NOTES.md /
learning-records/ and the deep-dive/fundamentals .md sources. The book lessons are
now sourced from their converted .mdx; the .md are backed up locally in case the
cleaner markdown is wanted as the future source.

Project stays in astro-poc/ (source) -> docs/ (output). Note: check-broken-links.js
still assumes relative links, so its base-absolute "misses" (/engineering-learning-hub/…)
are GitHub-Pages-valid — follow-up to make it base-aware.
The Astro project moved from astro-poc/ to the repo root (package.json,
astro.config.mjs with outDir now ./docs, src/, public/, tsconfig, pnpm files,
scripts). docs/ stays the build output — GitHub Pages serves main -> /docs
unchanged, output byte-identical (verified).

- Removed the obsolete EPUB-reader cruft (reader.html, server.js, the root
  package.json/pnpm-lock — gitignored local) and dropped the /package.json +
  /pnpm-lock.yaml ignore anchors so the Astro manifests track at root.
- Retired migration-superseded tooling: inject-analytics.js, inject-a11y.py,
  inject-lesson-feedback.py, inject-lesson-endnote.py (the layouts do this now),
  build-reference-pages.py (pandoc -> Astro glossary/resources collections),
  build-card-detail.js + wire-og-cards.js (old hub card system), README-ASTRO-POC.md.
- Renamed the CommonJS validators to .cjs (check-broken-links, check-hub-hooks,
  validate-content) — required now that the root package.json is "type":"module".

Build from root: `pnpm install && pnpm build` -> docs/ (96 pages, 0 real broken
links, hub hooks PASS 19/19, mdx + frontmatter 48/48). Kept scripts: check-mdx.mjs,
check-frontmatter.mjs, check-hub-hooks.cjs, check-broken-links.cjs,
validate-content.cjs, build-og-cards.py.
Replaces the "Quietype Indigo" palette with an engineering-notebook
identity across both dark and light themes:

tokens.css (public/assets/ source + docs/assets/ output):
- Dark: obsidian surfaces (#0B1020), amber primary accent (#F59E0B),
  cyan secondary (#22D3EE), sky-blue links (#38BDF8)
- Light: slate-white surfaces (#F8FAFC), dark amber (#D97706), teal secondary
- New canonical token names (--surface, --text, --border, --link, --code-bg…)
- Old names (--card, --ink, --line, --chip, --good, --bad, --warn) kept as
  migration aliases — all 96 pages resolve with zero markup edits

index.astro: 10 hardcoded hex values replaced with tokens or brand constants:
  hero gradient → always-dark obsidian, topbar blur → var(--bg), badges/pills
  → warning/bg tokens, OG card gradient → amber+cyan, active chip → var(--bg)

lesson.css: figure bg #fffff8 → var(--surface); links a{} → var(--link)
  with hover state using var(--link-hover)

validate-content.cjs: exclude 404.html from indexable/sitemap gate
BaseLayout.astro: additive robots prop (default index,follow; 404 uses noindex)
SiteFooter.astro: avatar src base-absolute (was bare-relative, would 404 on nested pages)
src/pages/404.astro: branded 404 page (noindex, obsidian/amber themed, base-absolute links)
URLs like /ai-agents/lessons/0001-ai-agents-from-first-principles.html
are replaced by /ai-agents/lessons/ai-agents-from-first-principles.html.
Physical MDX filenames are unchanged (ordering preserved); only the
routed path, cross-references, figure dirs, and sitemap are updated.

Also fixes check-broken-links.cjs to resolve root-relative
/engineering-learning-hub/ paths against docs/ (the site root).
Raw relative hrefs like "ai-agents/lessons/..." resolved from the
document root when the hub page URL lacked a trailing slash, producing
/ai-agents/... paths that 404 in both dev and production. All three
link sites (lchip, start button, reference pills) now emit
base-absolute paths.
…ping content in <p>

Multi-line <sup><a ...>\n  N\n</a></sup> patterns caused MDX to wrap
the footnote number in a <p> block, making it render as a standalone
block element instead of an inline superscript. Collapsed all 197
occurrences across all content files to single-line form.
- Add .github/workflows/deploy.yml: builds Astro site with pnpm,
  runs validate-content + check-broken-links, deploys to GitHub Pages
  on push to main (PRs get build+validate only, no deploy).
- Add docs/ to .gitignore and untrack the 300+ generated HTML files —
  the build output is now produced by CI, not committed to the repo.
- Remove content-validation.yml and link-check.yml — both are now
  superseded by the build job in deploy.yml (validation runs post-build
  on every push/PR, against the freshly built docs/ rather than
  committed files).

After merging, update GitHub Pages source from
  Settings → Pages → Source: "Deploy from a branch"
to
  Source: "GitHub Actions"
Make the site read as a calm, technical engineering knowledge base rather
than an amber-heavy dashboard. Amber now signals only genuine highlights;
slate carries structure and cyan carries the technical/per-track identity.

Hub cards (src/pages/index.astro):
- .tile left border: amber (--tc) -> neutral (--line); only the curated
  START HERE card ([data-here]) keeps the amber edge.
- .start button: was a solid amber block on every card; now a quiet amber
  ghost (outline) by default, fills on hover. The two cards that ARE the
  primary action -- START HERE and in-progress Continue -- stay filled.
- .tag keyword chips + .cnt lesson-count pill: amber-tinted -> neutral slate
  (--bg-soft / --chip / --line).
- a.lchip i lesson-number badge: amber fill -> neutral chip with cyan numeral.

Topic chips (lesson.css + Reference/Interview/Roadmap layouts):
- .ltags .lt: amber fallback -> neutral slate. Drops the 6-color rainbow
  nth-child cycle in ReferenceLayout (was the loudest non-amber offender).

Per-track tokens (tokens.css):
- All 15 --track-* unified from amber to the secondary cyan accent, so card
  icon tints read as one cohesive technical identity, not a rainbow.

No layout/markup changes, no new deps. Lesson body links already used --link
(cyan). Build green; validate-content + check-broken-links both pass.
check-mdx.mjs and check-frontmatter.mjs were sweep tools for the bulk
MDX conversion -- they report all syntax/frontmatter errors in one pass
instead of build's one-at-a-time. The migration is done and the site
builds green, so `astro build` (which parses MDX and frontmatter with the
same compilers) now fully covers what they checked. Neither was wired into
CI or package.json; they only referenced each other in comments.

Kept: build-og-cards.py (regenerates committed OG card PNGs) and
check-hub-hooks.cjs (the only guard that analytics/ARIA DOM hooks survive
a component refactor).

No CI change. Actions minutes are free on this public repo regardless.
Run `prettier --write .` across the tracked source so the about-to-be-added
pre-commit hook starts from a clean baseline (otherwise the first edit to each
stale file would carry an unrelated reformat blast).

Markup/frontmatter only — the dense Tufte CSS lives in JS template strings
(set:html), which Prettier does not touch, and public/assets + src/content +
figures stay .prettierignore'd. Build green; validate-content + broken-links pass.
Adds a fast, format-only pre-commit gate so committed source stays
consistently formatted without anyone remembering to run `pnpm format`.

- husky: installs the git hook reproducibly via the `prepare` script, so a
  fresh `pnpm install` wires it up automatically (no manual setup per clone).
- lint-staged: runs `prettier --write` on ONLY the staged files of the
  formattable types ({js,cjs,mjs,ts,astro,json,md,yml,yaml}) and re-stages
  them. Sub-second; never blocks a commit over whitespace.

Scope is deliberate: the heavy gates (astro build, validate-content,
check-broken-links) stay in CI — they need a built docs/ and are too slow to
run on every commit. .prettierignore now also excludes the generated docs/
outDir and the machine-managed pnpm-lock.yaml.
`prepare` runs on every `pnpm install`, so husky was being set up in CI too,
where the pre-commit Prettier hook is pointless — CI never commits, and
formatting is a local concern (CI validates the built site, it does not format
source).

Route `prepare` through .husky/install.mjs, which exits early when the CI env
var is set. GitHub Actions exports CI=true automatically, so deploy.yml needs
no change: `pnpm install --frozen-lockfile` simply no-ops the hook setup in CI
and installs hooks as normal on local machines.
Adds a commit-msg git hook that lints every local commit message against
@commitlint/config-conventional. The repo already follows this convention
(feat / fix / chore / refactor / style / docs, optional (scope), trailing !
for breaking changes) — this makes it non-optional so the history stays
machine-readable (changelog/release tooling, easy scanning).

- commitlint.config.js extends config-conventional with no custom rules;
  defaults fit (header <= 100, known type, non-empty subject). Scopes stay
  free-form so it guides without nagging.
- .husky/commit-msg runs `commitlint --edit "$1"`. Local-only: CI never
  commits and husky is not installed in CI (install.mjs CI guard), so
  deploy.yml is untouched.
Squash merges use the PR title as the commit subject, so a non-conventional
title would land an off-convention commit on the default branch even though
local commits are linted. This adds a lightweight workflow that runs the
repo's own commitlint config against the PR title.

- Separate from deploy.yml on purpose: it must fire on the `edited` event
  (title fixes), and adding that to the build workflow would rebuild the whole
  site on every title/description edit. `synchronize` is included so the check
  re-stamps each head SHA (needed if it becomes a required status check).
- The title is attacker-controlled, so it is passed via the PR_TITLE env var
  and never interpolated into the shell command (no injection surface).
- Reuses commitlint.config.js — one source of truth for local commits AND PR
  titles. Self-skips nothing in CI: husky isn't installed (CI guard), and this
  job only runs `commitlint`, not the build.
…text

Small follow-up pass on the Obsidian+Amber+Cyan palette. Most of the prompt's
targets (neutral card borders with amber only on the START HERE card, cyan
links, neutral tags, cyan hero tagline) were already in place from the prior
refinement; this fixes only the three things still off:

- Active filter chip (.fchip.is-active): dark ink (#111827) instead of white on
  the amber fill — calmer, not glowing, and fixes a real light-theme AA failure
  (white-on-amber was ~2.9:1). One value works in both themes, so the per-theme
  override is dropped; explicit box-shadow:none so it never reads as bulky. Adds
  a softer --accent-soft focus ring on the chips.
- Normal Start button (.start ghost): was muddy/brown — amber 12% fill over the
  navy surface. Now brighter --accent-soft text with a lighter fill (9%) and
  border (26%) so it reads as a clean outlined CTA. Hover/featured/Continue
  fills are unchanged.
- Dark-theme muted text: --text-muted #A7B0C0 -> #B6C0D1, --text-soft #7C8798 ->
  #8D98AB. Card descriptions/secondary text read easier while staying secondary;
  light theme untouched.

No layout/content/markup changes. Build green; validate-content + broken-links
pass.
The bottom sheet (openSheet) reads each lesson chip's literal href attribute
and looks it up in window.CARD_DETAIL to show the lesson's blurb. After lesson
hrefs gained the GitHub-Pages base prefix (TrackCard renders
`${base}${lesson.href}`), the DOM href became
"/engineering-learning-hub/<track>/lessons/<slug>.html" while CARD_DETAIL was
still keyed by the base-less "<track>/lessons/<slug>.html" — so every
DETAIL[href] lookup missed and no .cs-d description was appended.

Key cardDetail with the same `${base}${lesson.href}` the DOM uses, so the key
space matches the chip hrefs. Verified the built CARD_DETAIL key and the
a.lchip href are now identical. Single inline source (derived from tracks)
unchanged otherwise. Build + validate-content + broken-links green.
The card-detail sheet shows a per-lesson blurb only for lessons present in
CARD_DETAIL (derived from lessons[].blurb). The 6 single-lesson AI-eng tracks
(ai-evaluation, production-ai-architecture, ai-security, ai-infrastructure,
domain-agent-design, advanced-ai-systems) never had a blurb — not a migration
regression (the old prebuilt map had no lesson keys for them either), but it
left each of those cards showing one lesson row with no description.

Add a blurb to each, sourced verbatim from that lesson's own frontmatter
`description` (the same kind of text every other blurb already uses — no new
copy invented). Every lesson chip now resolves to a blurb: built CARD_DETAIL
has 48 keys for 48 lesson chips, 0 missing. Build + both gates green.
public/assets/card-detail.js was the old pre-built CARD_DETAIL map (stale
0NNN--prefixed keys). Nothing loads it — index.astro derives window.CARD_DETAIL
inline from lessons[].blurb — yet it still shipped to docs/assets/ as dead
weight. Remove it.

Fix the comments that still pointed at it:
- track.ts (x2): blurb is emitted into CARD_DETAIL from lessons[].blurb inline,
  not "folded in from card-detail.js".
- tracks.ts: drop the card-detail.js reference and the now-false claim that the
  6 single-lesson tracks carry no blurb (they all do now).

The one surviving mention (index.astro) correctly says there is NO card-detail.js
asset, so it stays. Build + validate-content + broken-links green.
Follow-up to removing the orphan card-detail.js: the doc comments still said
blurb was "folded in from card-detail.js" and that the 6 single-lesson tracks
carry no blurb. Both are now false — blurb is authored in lessons[].blurb and
emitted into window.CARD_DETAIL inline by index.astro, and every lesson now has
one. (These two files were missed by the prior commit because the `git rm`
pathspec aborted the combined `git add`.)
The 5-volume backend-mastery series was labelled "Book 1"…"Book 5" in roadmap
titles, lesson kickers/metalines, cross-references, diagram captions and the
EPUB/deep-dive cover art. That collided with the site's existing term "Track"
(a subject area — the hub has ~15), and the covers literally read
"A GUIDED LEARNING TRACK · BOOK 4". Rename the volume axis to "Part N" so the
two levels stay distinct and consistent: Track = subject, Part = volume,
Lesson = chapter within.

Scope (35 files): numbered "Book N"/"Books N" and all-caps "BOOK N" → Part/PART,
plus the navigational lowercase references (roadmap intros "this book →
this part", "next book → next part", "five-book series", "four books of theory").

Deliberately NOT touched: the calendar verb ("Book 30 min with Sam"), EPUB
filenames (book-N-….epub), facebook/rocksdb URLs, the REST hotel-booking
domain, runbook/bookmark/textbook, real books (the Google SRE Book, REST API
design books), idioms ("oldest bug in the book", "open-book exam"), librarian
world-analogies, and in-prose rhetorical metaphors ("holds the whole book")
where "Part" would read worse.

Supersedes the earlier buggy Book→Lesson find-replace (discarded — it collided
"Book 1, Lesson 8" into "Lesson 1, Lesson 8" and clobbered the calendar verb).
Build + validate-content + broken-links green.
Replace implicit array-position ordering with a deterministic, documented
hierarchy in one place (src/data/sortTracks.ts), so the grid and lesson lists
never drift and publish date is never the primary key.

Order:
- Tracks (sortTracksForHub): startHere first → manual `order` asc →
  publishedAt desc → title asc (stable fallback).
- Lessons (sortLessons): `order` asc → publishedAt asc → title asc; an unset
  `order` keeps the authored array position, which is already the learning
  sequence — so lessons stay learning-first, never newest-first.
- sortByLatest (publishedAt desc → updatedAt desc → title) is provided for a
  future date-first "Latest" section; no such section exists today.

Data model (src/schema/track.ts):
- Add `order` (optional int) to tracks and lessons — the manual sort key,
  decoupled from array source position.
- Rename track `added` → `publishedAt` (first-published date). The DOM
  attribute stays `data-added`, so the NEW-pill/analytics contract is unchanged
  (TrackCard now emits data-added={track.publishedAt}).
- Add optional `updatedAt` (freshness) for the Latest sort.
- publishedAt is a TIEBREAK only and is never used to drive learning sequence.

tracks.ts: seed explicit order 1..15 (matching prior visual order) and set
Context Engineering startHere:true so both recommended entry points float first
(matches the hero copy that recommends both; previously only AI Agents was
flagged). Lessons keep authored order — no per-lesson churn.

Every comparator ends in a title compare, so ordering is fully deterministic
and stable regardless of engine sort. Build + validate-content + broken-links
green; verified render order (ai-agents, context-engineering, then order 3..15)
and learning-first lessons (★ fundamentals first in deep-dive tracks).
@dineshbyte dineshbyte closed this Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant