580 update roadmap - #581
Conversation
Removes the old single-page roadmap (_index.md, 2025_roadmap.png) in favor of the new interactive roadmap site, and adds its remaining supporting files (404 page, build script, JS modules, proposal PDF). Also fixes index.html referencing removed #sort-key/#sort-dir controls, which threw on load and left the "All Projects" grid empty.
Drops the timeline/milestone display from project detail pages (project.html, project.js, project.css) and removes the underlying timeline field from project frontmatter, build.py, and the generated data/projects.js.
Replaces the standalone index.html with content/about/roadmap/_index.md, using the same front matter conventions as sibling About pages (organization, team, branding). The intro text is now proper markdown; the dynamic project grid is preserved as embedded HTML/JS since goldmark unsafe rendering is already enabled site-wide.
Swaps the Google Fonts Inter/JetBrains Mono import for local Montserrat @font-face rules pointing at the same font files the Hugo theme already serves, so the roadmap pages match the rest of the site's typography instead of loading a separate external font family.
project.html was still a standalone HTML document that Hugo copied verbatim, so clicking into a project dropped visitors out of the site's nav/header entirely. Give it the same treatment _index.md already got: strip it down to a content fragment with front matter so it renders inside the shared Hugo layout, now at the clean URL /about/roadmap/project/ instead of project.html. Updates the URL-building helpers, two hardcoded links, and one in-body project link accordingly, and hides the theme's generic page title in favor of the dynamic project hero. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Drop "A peptide force field", "Adopt Presto", and "Refactor OpenFF Toolkit" from the proposal. Also clears the now-dangling dependency on peptide-forcefield from protein-forcefield.md, regenerates data/projects.js, and updates the project count in README.md (23 -> 21). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Category infrastructure, marked as alternative. Content (summary, goals, benefits, FTE, metrics, go/no-go gates) is left as TODO placeholders for staff to fill in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adapts the full proposal text into the summary, goals, and benefits fields, condensed and reoriented for an internal staff audience rather than a funding pitch. Also infers infra_updates and benchmarking as pipeline stages from the described work. FTE and go/no-go gate date are left blank — the source text gives a 90% success target but no FTE estimate or a dated gate, and I didn't want to invent either. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ield Marks "A folded protein force field" as a dependency, and mirrors it as an "enables" entry on protein-forcefield.md to keep the dependency graph consistent in both directions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6 months science (new code), 6 months science (experiments), 12 months infrastructure. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Category infrastructure, marked as alternative. Content (summary, goals, benefits, FTE, metrics, go/no-go gates) is left as TODO placeholders for staff to fill in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sync generated data with the manual edits to mlip-setup-inference.md (commit 81e0db1). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Category infrastructure, marked as alternative. Content (summary, goals, benefits, FTE, metrics, go/no-go gates) is left as TODO placeholders for staff to fill in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adapts the proposal text into summary, goals, benefits, and metrics, focused on the OpenFF-side work (active-learning-capable fitting pipeline, QCArchive/OpenFF interoperability). The QCArchive-side agent-friendliness work (chemical search, permissions) is scoped as an external-goal metric rather than an OpenFF goal, and FTE is set to 24 infrastructure / 12 science (new code) / 12 science (experiments) months. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Category usability, marked as alternative. Content (summary, goals, benefits, FTE, metrics, go/no-go gates) is left as TODO placeholders for staff to fill in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds summary, goals, benefits, FTE, stages, and metrics based on the proposal for making OpenFF and Open Free Energy AI-native: MCP interfaces, a hardened agentic workflow built on Genentech's OpenFE agent, guardrails against invalid calculation setups, and Alchemiscale execution-state improvements. Goals that involve OpenFE, Genentech, or Alchemiscale rather than OpenFF's own codebase are marked as external. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_projects/*.md and README.md were being picked up as regular content pages (Hugo has no special handling for a leading-underscore directory name), so every project appeared twice on the roadmap page: once as a JS-rendered card and once via the theme's list.html looping over Paginator.Pages. Excludes both via ignoreFiles in config.toml. project.html (the project detail template) is also excluded from page listings via _build.list: never, since it's meant to be navigated to directly with a ?id= query param, not listed as its own article. Verified via a full before/after site build diff that no other page outside content/about/roadmap/ is affected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
This commit (edit: 40f2d36) modified config.toml, so I consider it this only high-risk Claude commit (meaning high risk of breaking the website). I had Claude check the entire site diffs for anything that could have broken, and the only thing that turned up was a sort order of some entries that (Claude claimed) were an artifact of obscure Hugo tie-breaking rules for ranking unordered lists. My manual spot-checks couldn't find anything else affected by the changes either, but please check any other way you can think of.
Yoshanuikabundi
left a comment
There was a problem hiding this comment.
Hi, I've done a quick once over after noticing that dark mode looks pretty bad. I think Claude can probably take care of these items itself pretty handily, probably with a lot of "oh great point" "good catch" etc. Happy to do another round later on the actual aesthetics!
| /* ---- Theme toggle button --------------------------------- */ | ||
| .theme-toggle { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 0.4rem; | ||
| padding: 0.3rem 0.65rem; | ||
| background: var(--color-surface-2); | ||
| border: 1px solid var(--color-border); | ||
| border-radius: 999px; | ||
| color: var(--color-text-muted); | ||
| font-size: 0.75rem; | ||
| font-weight: 500; | ||
| font-family: var(--font-sans); | ||
| cursor: pointer; | ||
| transition: border-color 0.15s, color 0.15s, background 0.15s; | ||
| white-space: nowrap; | ||
| margin-left: auto; | ||
| flex-shrink: 0; | ||
| } | ||
|
|
||
| .theme-toggle:hover { | ||
| border-color: var(--color-border-light); | ||
| color: var(--color-text); | ||
| } | ||
|
|
||
| .theme-toggle .toggle-icon { font-size: 0.9rem; line-height: 1; } | ||
|
|
There was a problem hiding this comment.
This button is never used! I think this CSS can safely be deleted, and should be especially if the dark theme above is removed:
| /* ---- Theme toggle button --------------------------------- */ | |
| .theme-toggle { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.4rem; | |
| padding: 0.3rem 0.65rem; | |
| background: var(--color-surface-2); | |
| border: 1px solid var(--color-border); | |
| border-radius: 999px; | |
| color: var(--color-text-muted); | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| font-family: var(--font-sans); | |
| cursor: pointer; | |
| transition: border-color 0.15s, color 0.15s, background 0.15s; | |
| white-space: nowrap; | |
| margin-left: auto; | |
| flex-shrink: 0; | |
| } | |
| .theme-toggle:hover { | |
| border-color: var(--color-border-light); | |
| color: var(--color-text); | |
| } | |
| .theme-toggle .toggle-icon { font-size: 0.9rem; line-height: 1; } |
| /* ---- Custom Properties — Dark (default) ------------------ */ | ||
| :root { | ||
| --color-bg: #0f1117; | ||
| --color-surface: #1a1d27; | ||
| --color-surface-2: #222636; | ||
| --color-border: #2d3148; | ||
| --color-border-light: #3d4260; | ||
| --color-text: #e2e8f0; | ||
| --color-text-muted: #8892a4; | ||
| --color-text-faint: #4a5568; | ||
| --color-accent: #6366f1; | ||
| --color-accent-hover: #818cf8; | ||
|
|
||
| /* Category colors — must match projects.js */ | ||
| --cat-infrastructure: #6366f1; | ||
| --cat-domain: #10b981; | ||
| --cat-accuracy: #f59e0b; | ||
| --cat-benchmarking: #3b82f6; | ||
| --cat-usability: #ec4899; | ||
|
|
||
| /* Maturity colors */ | ||
| --mat-early: #f97316; | ||
| --mat-mid: #eab308; | ||
| --mat-late: #22c55e; | ||
| --mat-end: #94a3b8; | ||
| --mat-full: #a78bfa; | ||
|
|
||
| --radius-sm: 4px; | ||
| --radius-md: 8px; | ||
| --radius-lg: 12px; | ||
| --radius-xl: 16px; | ||
|
|
||
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.4); | ||
| --shadow-md: 0 4px 16px rgba(0,0,0,0.5); | ||
| --shadow-lg: 0 8px 32px rgba(0,0,0,0.6); | ||
|
|
||
| --font-sans: "Montserrat", system-ui, -apple-system, sans-serif; | ||
| --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; | ||
|
|
||
| --max-width: 1400px; | ||
| --nav-height: 60px; | ||
|
|
||
| /* Graph node text (SVG fill fallback via CSS variable) */ | ||
| --graph-node-text: #e2e8f0; | ||
| } | ||
|
|
||
| /* ---- Light mode ------------------------------------------ */ | ||
| [data-theme="light"] { | ||
| --color-bg: #f8f9fc; | ||
| --color-surface: #ffffff; | ||
| --color-surface-2: #f1f3f8; | ||
| --color-border: #dde1ee; | ||
| --color-border-light: #c8cee0; | ||
| --color-text: #1a1d2e; | ||
| --color-text-muted: #5a6378; | ||
| --color-text-faint: #9ba3b8; | ||
| --color-accent: #5254cc; | ||
| --color-accent-hover: #4547b0; | ||
|
|
||
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.08); | ||
| --shadow-md: 0 4px 16px rgba(0,0,0,0.1); | ||
| --shadow-lg: 0 8px 32px rgba(0,0,0,0.12); | ||
|
|
||
| --graph-node-text: #1a1d2e; | ||
| } | ||
|
|
There was a problem hiding this comment.
Dark mode looks really bad, as only the roadmap has this feature:
I'd suggest just removing the [data-theme] selector and making light mode the only mode:
| /* ---- Custom Properties — Dark (default) ------------------ */ | |
| :root { | |
| --color-bg: #0f1117; | |
| --color-surface: #1a1d27; | |
| --color-surface-2: #222636; | |
| --color-border: #2d3148; | |
| --color-border-light: #3d4260; | |
| --color-text: #e2e8f0; | |
| --color-text-muted: #8892a4; | |
| --color-text-faint: #4a5568; | |
| --color-accent: #6366f1; | |
| --color-accent-hover: #818cf8; | |
| /* Category colors — must match projects.js */ | |
| --cat-infrastructure: #6366f1; | |
| --cat-domain: #10b981; | |
| --cat-accuracy: #f59e0b; | |
| --cat-benchmarking: #3b82f6; | |
| --cat-usability: #ec4899; | |
| /* Maturity colors */ | |
| --mat-early: #f97316; | |
| --mat-mid: #eab308; | |
| --mat-late: #22c55e; | |
| --mat-end: #94a3b8; | |
| --mat-full: #a78bfa; | |
| --radius-sm: 4px; | |
| --radius-md: 8px; | |
| --radius-lg: 12px; | |
| --radius-xl: 16px; | |
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.4); | |
| --shadow-md: 0 4px 16px rgba(0,0,0,0.5); | |
| --shadow-lg: 0 8px 32px rgba(0,0,0,0.6); | |
| --font-sans: "Montserrat", system-ui, -apple-system, sans-serif; | |
| --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; | |
| --max-width: 1400px; | |
| --nav-height: 60px; | |
| /* Graph node text (SVG fill fallback via CSS variable) */ | |
| --graph-node-text: #e2e8f0; | |
| } | |
| /* ---- Light mode ------------------------------------------ */ | |
| [data-theme="light"] { | |
| --color-bg: #f8f9fc; | |
| --color-surface: #ffffff; | |
| --color-surface-2: #f1f3f8; | |
| --color-border: #dde1ee; | |
| --color-border-light: #c8cee0; | |
| --color-text: #1a1d2e; | |
| --color-text-muted: #5a6378; | |
| --color-text-faint: #9ba3b8; | |
| --color-accent: #5254cc; | |
| --color-accent-hover: #4547b0; | |
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.08); | |
| --shadow-md: 0 4px 16px rgba(0,0,0,0.1); | |
| --shadow-lg: 0 8px 32px rgba(0,0,0,0.12); | |
| --graph-node-text: #1a1d2e; | |
| } | |
| /* ---- Custom Properties ------------------ */ | |
| :root { | |
| /* Category colors — must match projects.js */ | |
| --cat-infrastructure: #6366f1; | |
| --cat-domain: #10b981; | |
| --cat-accuracy: #f59e0b; | |
| --cat-benchmarking: #3b82f6; | |
| --cat-usability: #ec4899; | |
| /* Maturity colors */ | |
| --mat-early: #f97316; | |
| --mat-mid: #eab308; | |
| --mat-late: #22c55e; | |
| --mat-end: #94a3b8; | |
| --mat-full: #a78bfa; | |
| --radius-sm: 4px; | |
| --radius-md: 8px; | |
| --radius-lg: 12px; | |
| --radius-xl: 16px; | |
| --font-sans: "Montserrat", system-ui, -apple-system, sans-serif; | |
| --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; | |
| --max-width: 1400px; | |
| --nav-height: 60px; | |
| --color-bg: #f8f9fc; | |
| --color-surface: #ffffff; | |
| --color-surface-2: #f1f3f8; | |
| --color-border: #dde1ee; | |
| --color-border-light: #c8cee0; | |
| --color-text: #1a1d2e; | |
| --color-text-muted: #5a6378; | |
| --color-text-faint: #9ba3b8; | |
| --color-accent: #5254cc; | |
| --color-accent-hover: #4547b0; | |
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.08); | |
| --shadow-md: 0 4px 16px rgba(0,0,0,0.1); | |
| --shadow-lg: 0 8px 32px rgba(0,0,0,0.12); | |
| /* Graph node text (SVG fill fallback via CSS variable) */ | |
| --graph-node-text: #1a1d2e; | |
| } | |
| --color-accent: #6366f1; | ||
| --color-accent-hover: #818cf8; | ||
|
|
||
| /* Category colors — must match projects.js */ |
There was a problem hiding this comment.
This comment is incorrect. These colors do appear in projects.js, but where they have to match is build.py which generates projects.js. They also appear in utils.js. In both cases, the JS files should be corrected to use the variable defined here to preserve a single source of truth and prevent things drifting out of alignment.
| export const CATEGORIES = { | ||
| infrastructure: { label: "Infrastructure / Fitting Pipeline", color: "#6366f1" }, | ||
| domain: { label: "Domain Expansion", color: "#10b981" }, | ||
| accuracy: { label: "Accuracy Improvements", color: "#f59e0b" }, | ||
| benchmarking: { label: "Benchmarking", color: "#3b82f6" }, | ||
| usability: { label: "Usability / Community", color: "#ec4899" }, | ||
| }; | ||
|
|
||
| export const MATURITY_COLORS = { | ||
| early: "#f97316", | ||
| mid: "#eab308", | ||
| late: "#22c55e", | ||
| end: "#94a3b8", | ||
| full: "#a78bfa", | ||
| }; |
There was a problem hiding this comment.
These should use the color CSS variables - just replacing the color strings with things like var(--cat-infrastructure) might work? Using the variable names defined in content/about/roadmap/css/main.css
| export const CATEGORIES = {{ | ||
| infrastructure: {{ label: "Infrastructure / Fitting Pipeline", color: "#6366f1" }}, | ||
| domain: {{ label: "Domain Expansion", color: "#10b981" }}, | ||
| accuracy: {{ label: "Accuracy Improvements", color: "#f59e0b" }}, | ||
| usability: {{ label: "Usability / Community", color: "#ec4899" }}, | ||
| }}; | ||
|
|
||
| export const STAGE_LABELS = {{ | ||
| infra_updates: "Upfront Infrastructure", | ||
| data_generation: "Data Generation", | ||
| fitting: "Fitting", | ||
| benchmarking: "Benchmarking", | ||
| release: "Release", | ||
| community_maintenance: "Community & Maintenance", | ||
| }}; | ||
|
|
||
| export const ALL_STAGES = ["infra_updates", "data_generation", "fitting", "benchmarking", "release", "community_maintenance"]; | ||
|
|
||
| export const MATURITY_COLORS = {{ | ||
| early: "#f97316", | ||
| mid: "#eab308", | ||
| late: "#22c55e", | ||
| end: "#94a3b8", | ||
| full: "#a78bfa", | ||
| }}; |
There was a problem hiding this comment.
These colors appear to be duplicates of those found in content/about/roadmap/css/main.css, they should be replaced with references to those CSS variables. This might be as simple as var(--cat-infrastructure), depending on what the JS does with them.
| // AUTO-GENERATED by build.py — do not edit manually. | ||
| // Edit _projects/*.md files instead, then re-run: python build.py |
There was a problem hiding this comment.
This seems really fragile, would be good to find a way for this (or an equivalent) to be run automatically by Hugo during the build process.
There was a problem hiding this comment.
This doesn't appear to be wired up anywhere, and putting a nonsense URL like http://localhost:1313/about/roadmap/asdf into the Hugo web server doesn't bring it up. It would be great if something like this could be wired up to the entire site, as we currently just have the GH Pages 404 page. I don't think there's any need for the roadmap to have its own 404 page.
| import frontmatter | ||
| import markdown | ||
| except ImportError: | ||
| print("ERROR: Missing dependencies. Run: pip install -r requirements.txt") |
There was a problem hiding this comment.
Asking most of the people who would plausibly run this script to install things to the system Python is probably a bit of a nonstarter - we should use a simple pixi setup, or a conda environment.yaml, or (best option) reimplement this script in Ruby or JS or whatever Hugo uses to write extensions.
There was a problem hiding this comment.
I asked Claude about using hugo-native features to replace this (Claude is at least pretty good at cleaning up its mistakes and shortsightedness when you identify them!) and it said the following:
Hugo can do this natively — it's basically the core of what Hugo is. The pieces you want:
Content sections + list templates are the main mechanism. Put the markdown files under
content/<section>/. Everything in the frontmatter surfaces in templates as.Params(plus the built-ins like.Title,.Date,.Weight), and the body is available as.Content(rendered HTML),.RawContent,.Plain, or.Summary. Then the section's template does the collation thatbuild.pywas doing, and emits your custom HTML directly:{{/* layouts/notes/section.html (Hugo ≥ 0.146; layouts/notes/list.html on older versions) */}} {{ define "main" }} <ul class="notes"> {{ range .Pages.ByDate.Reverse }} <li> <h2>{{ .Title }}</h2> <p class="meta">{{ .Params.category }}</p> {{ .Content }} </li> {{ end }} </ul> {{ end }}
where,sort,group,first,complementetc. cover essentially any filtering/ordering/grouping you'd do in Python, and taxonomies give you tag-style groupings with their own generated pages for free. This replaces both halves at once: collation happens at build time in the template, and the "JS rendering" becomes plain server-generated HTML.Suppressing per-item pages. If these files are data-like and shouldn't each get their own URL, cascade build options from the section's
_index.md:cascade: build: render: never list: localThe pages still appear in
.Pagesfor the section template but produce no standalone output.Module mounts if the markdown can't live under
content/for some reason:[[module.mounts]] source = "some/subdir" target = "content/notes"Hugo then treats that directory as if it were content, no file moves required.
Custom output formats, in case anything still genuinely needs JSON (a search index, say). JSON is a built-in output format; enable it per page kind and add a template for it:
[outputs] section = ["html", "json"]{{/* layouts/notes/section.json */}} {{- $items := slice -}} {{- range .Pages -}} {{- $items = $items | append (dict "title" .Title "url" .RelPermalink "body" .Plain) -}} {{- end -}} {{- $items | jsonify -}}This is the standard way people build client-side search indexes without a second build system — but given you're dropping the JS renderer, you probably only need the HTML output.
Two smaller things worth knowing. First, templates can fail the build:
{{ errorf "notes/%s missing required 'category'" .File.Path }}when a required frontmatter field is absent. Hugo has no built-in frontmatter schema validation, buterrorfguards in the list template (pluscascadefor defaults) get you build-time enforcement rather than silently-wrong output, which fits your error-before-runtime lean. Second, if "custom HTML" partly means customizing how the markdown itself renders (links, images, headings, code fences), that's render hooks —layouts/_markup/render-image.htmland friends — rather than anything in the list template.One caveat on paths: Hugo v0.146 (April 2025) flattened the template layout —
layouts/_default/list.htmlbecamelayouts/section.html,single.htmlbecamepage.html, partials moved tolayouts/_partials/. The old names still resolve for compatibility, so match whatever the project already uses, but new templates are better written against the new names.
| # content/about/roadmap/_projects/*.md are data sources for build.py | ||
| # (compiled into data/projects.js), not standalone Hugo pages. | ||
| # content/about/roadmap/README.md is repo documentation, not a page. | ||
| ignoreFiles = ["/_projects/", "README\\.md$"] | ||
|
|
There was a problem hiding this comment.
I think this would bite us in the future if we ever add another _projects directory or README.md file expecting it to build normally. The readme is probably safe but _projects could definitely come back to haunt us. Fortunately we can probably remove _projects if we port build.py to a Hugo-native format, or else put more of the path in that element or change it to something like "/_manually_built_data/" or something else less overloaded.
There was a problem hiding this comment.
Thanks for the suggestions. I thought this was ugly but didn't have a great idea of how else to approach it.
jaclark5
left a comment
There was a problem hiding this comment.
I read the agentic*.md and descent/smee files and didn't notice anything to change.
I have made a couple stylistic suggestions.
|
|
||
| /* ---- Custom Properties — Dark (default) ------------------ */ | ||
| :root { | ||
| --color-bg: #0f1117; |
| const fte = totalFTE(p); | ||
| return ` | ||
| <a href="${projectURL(p.id)}" class="card card-link" style=" | ||
| border-left: 3px ${p.recommended ? 'solid' : 'dotted'} ${cat.color}; |
…ting hex Category and maturity colors were hardcoded separately in build.py's generated output, data/projects.js, and js/utils.js, several of which were unused duplicates that had drifted out of sync with css/main.css. JS now reads the colors from :root via a cssVar() helper instead. Also fixes css/main.css itself: the last two commits removed the :root/[data-theme="light"] selectors around the --cat-*/--mat-* declarations but left the declarations behind, so they'd been sitting outside any rule (and thus ignored by the browser) since then. Regenerating data/projects.js via build.py also picked up the already-committed FTE correction for agentic-qc-data-ecosystem that the stale generated file hadn't reflected yet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
content/about/roadmap/404.html was a static file with roadmap-relative links that nothing ever served or linked to. layouts/404.html is a proper Hugo template extending the theme's baseof, so it renders with the site's real header/nav/footer. Hugo builds this into public/404.html automatically, which GitHub Pages serves for any unmatched path. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_projects/*.md were compiled by a Python script (build.py) into data/projects.js, which project.js/graph.js/the _index.md grid then read client-side to render everything via innerHTML. Nothing in CI ran build.py, so data/projects.js had to be regenerated and committed by hand -- exactly how it went stale and produced wrong FTE numbers earlier on this branch. Projects now live under content/about/roadmap/projects/ as real Hugo pages, rendered server-side by layouts/_default/roadmap-project.html (selected via a cascaded `layout: roadmap-project`) and the roadmap-grid shortcode on the overview page. Category/stage labels move to data/roadmap/*.yaml (Hugo site data) as the single source of truth. Bad category/stage values or dangling dependencies/enables references now fail the Hugo build with errorf instead of silently falling back to a default. Dropped along with this: the D3 dependency graph (graph.js/graph.css), which was already unwired from every page, and the grid's client-side sort-by-key code, which had no UI ever wired up to trigger it. Deleted build.py, requirements.txt, project.html, and the four now-unused JS files; removed the CSS left dangling by their removal. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Yoshanuikabundi
left a comment
There was a problem hiding this comment.
This is much better! The code is simpler to build, easier to understand, I think there's less of it, and it doesn't need to carry around a JSON-formatted copy of everything in _projects/!
My comments are mostly regarding the legibility of color choices, but there's a bit of layout and DRYness. There are no blockers, but I think most of my suggestions are straightforward improvements.
I do have one possibly controversial comprehensibility suggestion in roadmap/_index.md that suggests making the difference between alt and recommended projects clearer by breaking them into separate grids, and also using markdown instead of html to format their headings. But I could just be misreading the whole point.
Also, at the moment Hugo orders pages (roughly?) alphabetically, but I think it would be slightly more slick to order projects them by their pipeline stage, both in the grid and the next/prev buttons on each project page. I've pushed this as a PR to this PR's branch: #582
This is really neat and I'm looking forward to how easy its going to make updating the roadmap!
| - **Infrastructure** — Improving the software tools we use for fitting, to enable faster fitting experiments involving larger datasets and advanced fitting targets or methods. | ||
| - **Usability / Community** — Putting our software and models into the hands of real users and enabling them to advance their scientific programs. | ||
|
|
||
| The projects listed here are proposals developed by staff that represent our vision of steps we could take that move us toward our roadmap objectives. Projects that we believe to offer the most direct path toward value to the Open Force Field Consortium are listed first. Projects listed as "ALT" (dashed border) may be of interest to alternative funding sources. |
There was a problem hiding this comment.
Projects listed as "ALT" (dashed border) may be of interest to alternative funding sources.
Does this mean we're not actually planning to do them unless someone gives us more money? If so I think we should make them stand out more - make the ALT label pillbox like bright red with a tooltip that says, like, "Pending additional funding", or break the grid up to put them in an altogether separate category with its own explanation, something like
# Recommended projects
{{< roadmap-grid-rec >}}
# Alternative projects
These are projects we'd like to do, but presently require additional funding sources.
{{< roadmap-grid-alt >}}
And maybe a more idiomatic terminology like "stretch goal" would be clearer than "alternative"?
There was a problem hiding this comment.
This works! Amazing!
| <section style="margin-top:3rem;"> | ||
| <div style="display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-bottom:1.25rem; flex-wrap:wrap;"> | ||
| <h2 style="font-size:1rem; font-weight:600; color:var(--color-text-muted); text-transform:uppercase; letter-spacing:0.08em; margin:0;"> | ||
| All Projects | ||
| </h2> | ||
| </div> | ||
| {{< roadmap-grid >}} | ||
| </section> |
There was a problem hiding this comment.
(non-blocking) I'd be tempted to just do:
| <section style="margin-top:3rem;"> | |
| <div style="display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-bottom:1.25rem; flex-wrap:wrap;"> | |
| <h2 style="font-size:1rem; font-weight:600; color:var(--color-text-muted); text-transform:uppercase; letter-spacing:0.08em; margin:0;"> | |
| All Projects | |
| </h2> | |
| </div> | |
| {{< roadmap-grid >}} | |
| </section> | |
| ### All Projects | |
| {{< roadmap-grid >}} |
Looks approximately the same but more in line with the overall theme, and much easier to read in the source.
There was a problem hiding this comment.
| --max-width: 1400px; | ||
| --nav-height: 60px; | ||
|
|
||
| --color-bg: #f8f9fc; |
There was a problem hiding this comment.
| --color-bg: #f8f9fc; | |
| --color-bg: #ffffff00; |
I agree with Jen, this should be either white to match the site background, transparent, or just removed everywhere so that the background falls back to the containing element.
| {{/* Renders the "All Projects" card grid: recommended projects first, then alternatives. */}} | ||
| {{ $projSection := .Page.Site.GetPage "/about/roadmap/projects" }} | ||
| {{ $cats := .Page.Site.Data.roadmap.categories }} | ||
|
|
||
| <div id="project-grid" style="display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1rem;"> | ||
| {{ range (where $projSection.Pages "Params.recommended" true) }} | ||
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | ||
| {{ end }} | ||
| {{ range (where $projSection.Pages "Params.recommended" false) }} | ||
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | ||
| {{ end }} | ||
| </div> |
There was a problem hiding this comment.
Splitting the recommended and alternatives into different grids could be done like this:
| {{/* Renders the "All Projects" card grid: recommended projects first, then alternatives. */}} | |
| {{ $projSection := .Page.Site.GetPage "/about/roadmap/projects" }} | |
| {{ $cats := .Page.Site.Data.roadmap.categories }} | |
| <div id="project-grid" style="display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1rem;"> | |
| {{ range (where $projSection.Pages "Params.recommended" true) }} | |
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | |
| {{ end }} | |
| {{ range (where $projSection.Pages "Params.recommended" false) }} | |
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | |
| {{ end }} | |
| </div> | |
| {{/* Renders the "All Projects" card grid: recommended projects or alternatives based on recommended argument. */}} | |
| {{ $projSection := .Page.Site.GetPage "/about/roadmap/projects" }} | |
| {{ $cats := .Page.Site.Data.roadmap.categories }} | |
| {{ $recommended := .Get "recommended" | default true }} | |
| <div id="project-grid-{{cond $recommended "recommended" "alternate"}}" style="display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1rem;"> | |
| {{ range (where $projSection.Pages "Params.recommended" $recommended) }} | |
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | |
| {{ end }} | |
| </div> | |
Then {{< roadmap-grid recommended=true >}} displays the recommended grid and {{< roadmap-grid recommended=false >}} displays the alternates. So the bottom of _index.html could look something like:
<link rel="stylesheet" href="css/main.css">
### Recommended Projects
{{< roadmap-grid recommended=true >}}
### Alternative Projects
These projects may be achievable with additional funding.
{{< roadmap-grid recommended=false >}}
| {{ range (where $projSection.Pages "Params.recommended" true) }} | ||
| {{ partial "roadmap-grid-card" (dict "page" . "cats" $cats) }} | ||
| {{ end }} |
There was a problem hiding this comment.
Sorting this by pipeline stage rather than alphabetically by page source name would be swish!
There was a problem hiding this comment.
Much better than the Python script with runtime JS!
| <div class="project-nav"> | ||
| {{ if $prev }} | ||
| <a href="{{ $prev.RelPermalink }}" class="project-nav-link prev"> | ||
| ← <span> | ||
| <span class="nav-link-label">Previous</span> | ||
| <span class="nav-link-title">{{ $prev.Title }}</span> | ||
| </span> | ||
| </a> | ||
| {{ else }}<span></span>{{ end }} | ||
| {{ if $next }} | ||
| <a href="{{ $next.RelPermalink }}" class="project-nav-link next"> | ||
| <span> | ||
| <span class="nav-link-label">Next</span> | ||
| <span class="nav-link-title">{{ $next.Title }}</span> | ||
| </span> → | ||
| </a> | ||
| {{ end }} | ||
| </div> |
There was a problem hiding this comment.
This is neat for going through the projects one at a time, but we should try and order them by pipeline stage.
Sort projects by pipeline stage
Co-authored-by: Ashley Mitchell <yoshanuikabundi@gmail.com>
|
Upon discussion with @j-wags in standup and after checking the site render locally, I'm merging as-is so we have live links that folks have asked for. If it's broke, I'll fix it. |








Adapted the 2026 Roadmap Proposal https://github.com/openforcefield/openff-roadmap-proposal-2026 site into a permanent page on our main website. Removed some extraneous features, brought into line with the Hugo site, removed projects that were explicitly voted down by the advisory board, and added new projects reflecting new proposals in development. New projects were drafted with the help of Claude to summarize existing Letters of Intent for these proposals. Most modifications to page layout were done by Claude.