Skip to content

Add 'Linux on WebAssembly' blog post with scrollytelling layout#5328

Open
NathanFlurry wants to merge 3 commits into
mainfrom
nathan/linux-on-webassembly-post
Open

Add 'Linux on WebAssembly' blog post with scrollytelling layout#5328
NathanFlurry wants to merge 3 commits into
mainfrom
nathan/linux-on-webassembly-post

Conversation

@NathanFlurry

@NathanFlurry NathanFlurry commented Jun 24, 2026

Copy link
Copy Markdown
Member

Summary

Adds the "Linux on WebAssembly: a sandbox for AI agents, one syscall at a time" blog post, plus a reusable scrollytelling layout for in-depth (technical/guide) posts.

Post

  • Full narrative rewrite framed around the "fast, light, cheap sandbox for agents" tagline, building the OS up one syscall at a time: bare guest → processes → filesystem → network → compile toolchain → cheap-to-throw-away → orchestrated fleet.
  • New "Where the software comes from" section on the compile toolchain (registry of wasm32-wasip1 builds, patched std/wasi-libc routing to host_process/host_user/host_net).
  • "But does it run Doom?" payoff section.

Layout (ai-2027 style)

  • New scrolly: true frontmatter flag (in content.config.ts) opts a post into the layout.
  • SyscallDiagram is a single scroll-driven SVG pinned top-right, aligned with the top of the body, that advances through build steps as their data-syscall-step anchors cross the viewport. It releases at the bottom of the content (sticky containing block scoped to the article grid, not the footer).
  • Starting frame is the full architecture with labels stripped; it builds up (and zooms) as you scroll. Color-coded: ink = program, pine = syscall surface, sage = kernel.
  • Title is sized down and kept in the reading column. Mobile collapses to a single column with the diagram pinned on top.

Before publishing

  • Fill the bracketed placeholders in the post ([COLD_START_MS], [IDLE_MEM_MB], [SANDBOXES_PER_HOST], [WAKE_MS], [SYSCALL_COUNT], [HOST_CALL_COUNT]) with measured figures, or cut those sentences.
  • Upload the Doom recording to R2 at website/blog/2026-06-24-linux-on-webassembly-building-a-sandbox-one-syscall-at-a-time/doom.gif.
  • Verify the "what's still rough" paragraph matches the real implementation.

Test plan

  • pnpm run build is green (258 pages).
  • Visual review still recommended at ~1280–1440px and a phone width (diagram pin/release, alignment, color-coding).

@claude

claude Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

PR Review

This PR adds a "Linux on WebAssembly" technical blog post with a new scrollytelling layout: a two-column design (prose left, pinned SVG diagram right) driven by data-syscall-step anchors in the MDX, plus a table-of-contents rail for non-scrolly wide posts. The new BlogTableOfContents and SyscallDiagram React components are well-structured, and the Astro layout changes are clean. Two issues are publish blockers; the rest are correctness and maintenance concerns.


1. Production blocker — six unfilled metric placeholders in the post body

website/src/content/posts/2026-06-24-linux-on-webassembly-building-a-sandbox-one-syscall-at-a-time/page.mdx

Six bold [BRACKET] tokens appear inline in the prose — [COLD_START_MS], [IDLE_MEM_MB], [SANDBOXES_PER_HOST], [WAKE_MS], [SYSCALL_COUNT], [HOST_CALL_COUNT] — and will render literally to readers if the post is built and deployed before substitution. The "Making it cheap to throw away" and "Does it actually run?" sections both hinge on these figures for credibility; publishing with the tokens intact makes those paragraphs read as visibly unfinished.

The PR description lists filling these as a pre-publish step, but there is nothing in the build that fails or warns when they are present. Consider adding a CI lint (e.g. a grep -r '\[COLD_START' website/src/content/posts/) that fails if any placeholder survives, or gate the post behind unpublished: true until the figures are ready.


2. Production blocker — Doom GIF points to an asset not yet uploaded

website/src/content/posts/.../page.mdx, line 259 in the diff

![Doom running inside a wasm Linux sandbox](https://assets.rivet.dev/website/blog/2026-06-24-linux-on-webassembly-building-a-sandbox-one-syscall-at-a-time/doom.gif)

The PR description explicitly says "Upload the Doom recording to R2 at website/blog/2026-06-24-.../doom.gif" as a pre-publish step that has not been done. The URL references an asset that does not exist, producing a broken image at the post's payoff moment. Same fix: gate with unpublished: true until both the GIF is uploaded and the placeholders are filled.


3. Stale heading positions in ToC scroll spy after layout reflow

website/src/components/BlogTableOfContents.tsx, lines 43–58

useEffect(() => {
  const headings = getHeadings(toc);  // positions captured once
  function onScroll() {
    const top = window.scrollY;
    let cur = headings[0].id;
    for (const heading of headings) {
      if (top >= heading.top - LINK_MARGIN) cur = heading.id;
      else break;
    }
    setCurrent(cur);
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  // no resize listener
  ...

headings (with each element's .top offset) is computed once when the effect runs and then closed over by onScroll. If images or embeds in the article load after mount, they push all headings further down the page, but the stored offsets remain from before the reflow. The scroll spy will then highlight the wrong section until the reader refreshes. SyscallDiagram correctly adds a resize listener; BlogTableOfContents should do the same — either by adding a resize listener that re-runs getHeadings, or by recomputing positions inside onScroll itself (cheap, since getBoundingClientRect is already called there).


4. scrolly: true is silently coupled to the SyscallDiagram

website/src/content.config.ts + website/src/components/BlogArticle.astro

content.config.ts documents scrolly as a general-purpose layout opt-in ("Opt an in-depth post into the scrollytelling layout"), but BlogArticle.astro hardwires <SyscallDiagram client:load /> as the only diagram for any scrolly post. A future technical or guide post that sets scrolly: true without <div data-syscall-step="N" /> anchors will silently render the Linux/wasm architecture SVG frozen at its unlabeled preview frame, with no error or fallback. Either rename the flag to something post-specific (e.g. syscallDiagram: true), or make the diagram component configurable so the flag is truly generic.


5. Inline <style> block in SyscallDiagram

website/src/components/SyscallDiagram.tsx, the <style> JSX element

A ~55-line <style> string is embedded as a JSX child of the component. React treats it as a plain DOM node and does not deduplicate it across renders; in SSR + client hydration (Astro's island model), the same rules could appear once from server output and again on hydration. Extracting the styles to a co-located .module.css or a shared stylesheet import would remove the per-render injection concern entirely and make the CSS visible to tooling (linters, IDE autocomplete, bundle analysis).


6. Article header markup duplicated between scrolly and non-scrolly branches

website/src/components/BlogArticle.astro

The back link → timestamp → <h1> → description header block appears in both the {isScrolly ? ... : ...} branches, differing only in <h1> font size (text-3xl md:text-4xl vs. text-4xl md:text-[3.25rem]). Any future change to the header structure (adding a byline, a category badge, changing the date format) must be applied in both places and will silently diverge if only one branch is updated. Extracting a shared Astro component that accepts a compact prop for the size difference would keep this in one place.


Generated with Claude Code

@railway-app

railway-app Bot commented Jun 24, 2026

Copy link
Copy Markdown

🚅 Deployed to the rivet-pr-5328 environment in rivet-frontend

Service Status Web Updated (UTC)
kitchen-sink 😴 Sleeping (View Logs) Web Jun 24, 2026 at 9:37 pm
frontend-inspector 😴 Sleeping (View Logs) Web Jun 24, 2026 at 9:35 pm
frontend-cloud 😴 Sleeping (View Logs) Web Jun 24, 2026 at 9:32 pm
website 😴 Sleeping (View Logs) Web Jun 24, 2026 at 9:32 pm
ladle ✅ Success (View Logs) Web Jun 24, 2026 at 9:26 pm
mcp-hub ✅ Success (View Logs) Web Jun 24, 2026 at 9:25 pm

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