The version of MRoot in this case study has two presentations: a conventional portfolio and an IDE-style interface with an explorer, tabs, terminal, and command palette. Both show the same projects and writing.

The implementation detail that matters is where the content lives. Adding a project means writing one Markdown file, not updating a website record and then making a second copy for IDE mode.

This article describes the June 2026 implementation. It is not a fresh inspection of the current site, and the small demonstrations here are explanatory—not captures of its production editor.

01 / FIELD NOTESCompile the content at build time

A Vite plugin reads the files under content/, parses their frontmatter, and emits a plain data module exposed as virtual:content.

The published excerpt shows the shape of that module:

vite/content-plugin.ts / TypeScript
function buildModuleSource(contentDir: string): string {
  const projects = loadProjects(contentDir);
  const writing = loadWriting(contentDir);
  return `export const PROJECTS = ${JSON.stringify(projects)};
export const WRITING = ${JSON.stringify(writing)};
// …profile, skills, songs
`;
}
Source excerpt · not executed in this design sample · scroll code horizontally on narrow screens

src/data.ts re-exports the generated data. Website pages and IDE views read through that shared entry point rather than maintaining their own content collections.

The practical boundary is at build time. The browser receives the prepared data; this pipeline does not ship a Markdown parser for visitors to run. There is no performance number in the source, so that is an architectural description, not a benchmark claim.

FOLLOW THE CONTENT

Parse before the browser.

01 / AUTHORED CONTENT

Markdown + YAML

Projects and writing start as content files, not duplicated records for each interface.

Read the complete pipeline
Markdown + YAML
Projects and writing start as content files, not duplicated records for each interface.
Vite plugin
The plugin reads content and frontmatter and emits the virtual:content data module.
Shared exports
src/data.ts re-exports the generated data for the website and IDE views.
Prerendered HTML
vite-react-ssg prerenders routes. A postbuild step writes the sitemap and 404 page.
Conceptual walkthrough of the June 2026 implementation. No compiler or deployment runs here. Deployment on push is described in the article, not triggered by this figure.

02 / FIELD NOTESOne record, two presentations

The conventional site can turn a record into a project card. IDE mode can present that same record as a file in its explorer and content window. Those are different views of the data, not two separately authored versions.

Try changing the title or summary below. The card and file-like view both use your input. Reset brings back the example. This demonstration updates local browser text only: it does not write a Markdown file, save to MRoot, or run the build plugin.

EDIT ONE LOCAL RECORD

Two views. One source.

example-project.md ILLUSTRATIVE INPUT
ONE SHARED RECORD

WEBSITE PRESENTATION

A portfolio, two ways

A shared content collection, presented as a website and an IDE-style interface.

ILLUSTRATIVE PROJECT CARD
IDE PRESENTATION
01title: A portfolio, two ways02summary: A shared content collection, presented as a website and an IDE-style interface.03# Same data. Different rendering.
METADATA, NOT PROJECT SOURCE CODE

This example stays in this page’s memory. Nothing is saved or sent.

A local demonstration of shared data—not the real MRoot editor, a production screenshot, or an actual Vite build. Empty input gets a visible fallback.

The distinction also applies to the real site’s generated code previews. The original write-up says that the IDE project code window is derived from frontmatter, not from each project’s actual source. That can be a way to present metadata, but it should not be mistaken for a genuine implementation excerpt.

03 / FIELD NOTESA link should still identify the same work

The two modes share a URL space. In the documented implementation, a router pathname maps to an identifier the IDE understands.

The excerpt below shows the project-path rule, along with a lookup for static routes and a fallback:

src/lib/routeToIdeId.ts / TypeScript
export function routeToIdeId(pathname: string): string {
  const path = pathname.replace(/\/+$/, '') || '/';
  if (path in STATIC_ROUTES) return STATIC_ROUTES[path];
  const projectMatch = path.match(/^\/projects\/([^/]+)$/);
  if (projectMatch) return 'proj:' + projectMatch[1];
  return 'readme';
}
Source excerpt · not executed in this design sample · scroll code horizontally on narrow screens

For example, the project-path branch turns /projects/atlas-market into proj:atlas-market. The function also strips trailing slashes before matching.

The excerpt does not include the contents of STATIC_ROUTES. The local path demonstration therefore illustrates only the shown project-pattern branch and the readme fallback; it does not reconstruct the missing static-route table or verify which projects exist.

PROJECT-PATH MAPPING

The link identifies the work.

IDE IDENTIFIERproj:atlas-market

The project-path branch removes trailing slashes, then prefixes the slug with proj:.

Only the published project-pattern branch and readme fallback are demonstrated. STATIC_ROUTES is not supplied. An identifier does not verify that the project exists.

IDE mode itself is a preference stored in localStorage, so the choice can persist across pages and reloads. That preference is separate from the pathname that identifies the work.

04 / FIELD NOTESPrerender the pages, then deploy

The original build uses vite-react-ssg to prerender each route to HTML. A postbuild step writes the sitemap and 404 page, and the site deploys to Cloudflare Pages on push.

During development, the server watches content/. Editing a Markdown file updates the explorer, writing index, and command palette through that shared pipeline.

Those details describe the build and development process in the published account. The animation on this page is a walkthrough of the stages—not a live build log or deployment control.

05 / FIELD NOTESWhat I would improve

First, make the source of code previews unmistakable. The original project windows were generated from metadata. Showing a real, selected excerpt per project was the improvement identified in the write-up.

Second, split the large App.tsx view-model by presentation. The shared content does not require every view’s state and behavior to be gathered into one object.

Third, test the content plugin. The original account had no automated test around it. A frontmatter schema check was proposed to catch mistakes before they reach the build. This article does not claim that validation or test coverage has since been added.

06 / FIELD NOTESShare the content, not every interface decision

The website and IDE mode do not have to look alike to use the same data. That is the useful separation in this project: author a record once, then decide how each interface should present it.

The same idea shows up in the page you are reading. A visual explanation can make the pipeline easier to follow, but it should not obscure where the data comes from or what the underlying implementation actually does.

Source, dates, and what this page verifies

This is an editorial rewrite of the supplied project and technical article, describing the account published June 27, 2026. Original dates, code excerpts, and unfinished work are retained. The production repository, permissions, costs, and historical measurements have not been re-audited.

Interactive figures are local explanations. They do not call an API, send input, create content, or demonstrate production test coverage. The cumulative reference is not deployed.

Open the published source ↗