Skip to content

Establish Eleventy static-first scaffold with canonical parser, project map, and Lab scaffolding - #2

Merged
erinepshovel-code merged 1 commit into
mainfrom
codex/rebuild-interdependentway.org-as-dynamic-site
Jul 10, 2026
Merged

erinepshovel-code merged 1 commit into
mainfrom
codex/rebuild-interdependentway.org-as-dynamic-site

Conversation

@erinepshovel-code

Copy link
Copy Markdown
Contributor

Motivation

  • Replace the broken Vite/React preview with a static-first Eleventy-based build that preserves canonical provenance and supports progressive enhancement.
  • Recover the prior Eleventy/Pagefind information architecture and Article Lab intent while avoiding wholesale restores of historic branches.
  • Provide a reproducible build-time data pipeline that fetches/parses the canonical text and the organization's public repositories for durable pages.
  • Make missing editorial work and unresolved claims visible as hmmm rather than inventing balance or placeholder research.

Description

  • Add an Eleventy 3.1.2 scaffold and site shell with accessible layout, design tokens, and a small CSS system, and integrate Pagefind for search (.eleventy.js, src/_includes/layouts/base.njk, src/assets/css/site.css).
  • Implement build-time scripts to snapshot and parse the canonical source into src/_data/generated/canon.json (scripts/fetch-canon.mjs, scripts/parse-canon.mjs) and to fetch the public org repository snapshot into src/_data/generated/repos.json (scripts/fetch-github-org.mjs).
  • Generate static routes and templates for the four primary surfaces: The Way (/way/), Article Lab (/lab/), exact Source (/source/), and Projects (/projects/), including per-unit and per-repository pages and provenance displays (src/way/*, src/lab/*, src/source/*, src/projects/*).
  • Add validation, verification, and supporting scripts and tests (scripts/validate-content.mjs, scripts/verify-generated-routes.mjs, tests/*.test.mjs), documentation and runbooks (docs/*.md), and CI workflows for Pages and PR checks (.github/workflows/*.yml).

Testing

  • Ran npm install, npm run build, and the full npm run check sequence which executes build, validation, and tests, and the run completed successfully.
  • Automated unit tests (node --test tests/*.test.mjs) all passed with the repository-local scaffold, including canon-integrity.test.mjs, repo-coverage.test.mjs, research-ledger.test.mjs, and a basic site existence check.
  • Eleventy build completed and Pagefind indexing ran successfully (build produced site files and Pagefind indexed the generated pages).
  • Generated counts from the build: 24 canonical units discovered and rendered, 21 public repositories discovered and project pages generated, and Pagefind indexed the generated site pages.

Codex Task

@erinepshovel-code
erinepshovel-code merged commit 6843400 into main Jul 10, 2026
5 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2d565af09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3 to +4
push:
branches: [main]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Disable the stale root Pages deploy

On pushes to main, this workflow runs alongside the pre-existing .github/workflows/deploy.yml, which also triggers on push to main but uploads path: './' and deploys it without running the Eleventy build. If the new npm ci/npm run check path fails, or if the older workflow finishes after this one, GitHub Pages can publish the repository root/old site instead of the generated _site, bypassing the validation added here. Remove or retarget the old deploy workflow, or put both workflows under one deployment path/concurrency group.

Useful? React with 👍 / 👎.

Comment thread scripts/parse-canon.mjs
push(lines.length);
if(!units.length){ units.push({id:'source.full-text',title:'The Interdependent Way',section:'source',level:1,startLine:1,endLine:lines.length,content:text,hash:contentSha256}); sections.push({id:'source',title:'Source',level:1,line:1});}
for (const u of units){ const matches=[...u.content.matchAll(/\[(\d+|[a-z])\]/gi)]; for (const match of matches) notes.push({id:`${u.id}.note-${match[1]}`,unit_id:u.id,marker:match[0]}); }
const data={source:{repository:'The-Interdependency/a0',path:'interdependent_way.md',commit:process.env.CANON_COMMIT || 'local-snapshot',blob:null,retrievedAt:new Date().toISOString(),contentSha256,parserVersion},sections,units:units.map(({lines,...u})=>u),notes,edges:units.map(u=>({from:u.id,to:u.section,type:'unit-parent'}))};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the snapshot commit in generated provenance

npm run refresh:canon never sets CANON_COMMIT, while fetch-canon.mjs writes the fetched commit into the snapshot front matter. This line discards that metadata and emits commit: 'local-snapshot', and the Source template displays generated.canon.source.commit, so every rebuilt /source/... page loses the exact source commit users need for provenance. Parse the snapshot front matter or pass the fetched commit through before writing canon.json.

Useful? React with 👍 / 👎.

}
let fallback=false, repos=[];
try { repos=await fetchAll(); } catch(e){ fallback=true; try{repos=JSON.parse(await readFile('src/_data/snapshots/repos.last-known-good.json','utf8')).repositories;}catch{repos=[];} }
const mapped=repos.map(r=>({name:r.name,slug:r.name.toLowerCase().replace(/[^a-z0-9]+/g,'-'),html_url:r.html_url,description:r.description,archived:r.archived,fork:r.fork,default_branch:r.default_branch,topics:r.topics||[],license:r.license?.spdx_id||null,language:r.language,homepage:r.homepage,pushed_at:r.pushed_at,visibility:r.visibility||'public',hmmm:['Editorial project map missing until .interdependency/project.yml is reviewed.']}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve snapshot licenses when offline

When GitHub API access fails or OFFLINE=1 is used as documented in the runbook, repos is populated from src/_data/snapshots/repos.last-known-good.json, where license is already a string such as MPL-2.0. This raw-API mapping then reads r.license?.spdx_id, turning every license into null, and the next line writes that corrupted data back over the last-known-good snapshot. Handle normalized snapshot records separately or preserve string licenses before remapping.

Useful? React with 👍 / 👎.

Comment thread src/projects/repo.njk
size: 1
alias: repo
permalink: "/projects/{{ repo.slug }}/"
title: "Project: {{ repo.name }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compute generated page titles with eleventyComputed

Eleventy only evaluates template variables in permalink and eleventyComputed front matter; this title value remains the literal string Project: {{ repo.name }}. As a result, every generated project page gets the same broken browser/Pagefind title, and the same pattern is used in the generated unit templates. Move these dynamic titles under eleventyComputed so metadata reflects the current paginated item.

Useful? React with 👍 / 👎.

Comment thread scripts/parse-canon.mjs
function push(end){ if(current){ current.endLine=end; current.content=current.lines.join('\n').trim(); current.hash=createHash('sha256').update(current.content).digest('hex'); units.push(current); }}
for (let i=0;i<lines.length;i++){
const m=/^(#{1,6})\s+(.+?)\s*$/.exec(lines[i]);
if(m){ push(i); const level=m[1].length; const title=m[2].replace(/#+$/,'').trim(); if(level<=2){top=slug(title).replace(/^the-/, ''); sections.push({id:top,title,level,line:i+1}); article=0;} if(/article\s+[ivxlcdm0-9]+/i.test(title)) article++; const id=/article/i.test(title)?`${top}.article-${article||slug(title)}`:slug(title); current={id:`${id}-${i+1}`,title,section:top,level,startLine:i+1,lines:[lines[i]]}; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop deriving canonical IDs from line numbers

The docs added in this commit describe canon units as having stable IDs, but this line appends i + 1 to every ID and all unit permalinks are built from unit.id. Inserting a paragraph or heading anywhere above an existing article changes the line suffix and breaks existing /way/, /lab/, and /source/ links even when the article title/content did not change. Use a stable heading/article key plus a duplicate counter or hash instead of the source line number.

Useful? React with 👍 / 👎.

Comment thread scripts/parse-canon.mjs
}
push(lines.length);
if(!units.length){ units.push({id:'source.full-text',title:'The Interdependent Way',section:'source',level:1,startLine:1,endLine:lines.length,content:text,hash:contentSha256}); sections.push({id:'source',title:'Source',level:1,line:1});}
for (const u of units){ const matches=[...u.content.matchAll(/\[(\d+|[a-z])\]/gi)]; for (const match of matches) notes.push({id:`${u.id}.note-${match[1]}`,unit_id:u.id,marker:match[0]}); }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Deduplicate footnote markers per unit

For articles that contain both an inline marker and its definition, such as feed the hungry [1] followed by [1] wary..., this loop records both occurrences with the same note ID. The Lab template renders one Speaker B turn for every entry in generated.canon.notes, so affected units show each footnote twice and downstream consumers cannot treat note IDs as unique. Track markers already seen within a unit or parse definitions separately before emitting notes.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant