From bd1f2e475f214754ed656eecc6d4d291e92d8cc5 Mon Sep 17 00:00:00 2001 From: Benjamin Dichter Date: Sun, 11 Oct 2026 10:02:08 -0400 Subject: [PATCH 1/2] Redesign the Core NWB Tools page Lead with the six tools most users need, shown as denser horizontal cards with a task label, language tag and install one-liner. Group the remaining tools for extension authors and developers into compact columns, splitting schemas and specifications out of "Extending NWB". Also shrink the hero, add an in-page nav, constrain the intro width, darken link orange on tools pages to meet WCAG AA, and serve tool images resized as lazy-loaded WebP. Co-Authored-By: Claude Opus 5.5 --- assets/css/style.css | 300 ++++++++++++++++++ content/tools/core/_index.md | 35 +- content/tools/core/aqnwb.md | 2 + content/tools/core/hdmf-common-schema.md | 2 +- .../tools/core/hdmf-specification-language.md | 2 +- content/tools/core/matnwb.md | 2 + content/tools/core/neuroconv.md | 3 + content/tools/core/nwb-guide.md | 2 + content/tools/core/nwb-schema.md | 2 +- content/tools/core/nwbinspector.md | 3 + content/tools/core/pynwb.md | 3 + hugo.yaml | 3 + layouts/partials/tools/image.html | 16 + layouts/shortcodes/tool-columns.html | 4 + layouts/shortcodes/tool-grid.html | 66 +++- layouts/tools/list.html | 17 +- layouts/tools/single.html | 2 +- 17 files changed, 437 insertions(+), 27 deletions(-) create mode 100644 layouts/partials/tools/image.html create mode 100644 layouts/shortcodes/tool-columns.html diff --git a/assets/css/style.css b/assets/css/style.css index 9708038..709ac4d 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1239,6 +1239,306 @@ ol.custom-ordered-list li::before { } } +/* Tools pages: compact hero, in-page nav, readable intro */ +.hero--compact { + height: 230px !important; + overflow: hidden; +} + +.hero--compact h1 { + font-size: clamp(2rem, 7vw, 3rem) !important; + margin: 2.5rem 0 0 !important; + padding: 0 1rem; +} + +.tools-page.section { + padding-top: 48px !important; +} + +/* #d17128 is 3.4:1 on white; this shade meets WCAG AA (4.5:1) for body-size text */ +.tools-page .content a { + color: #b35a14 !important; +} + +.tools-page:not(.tools-page--single) .content > p { + max-width: 70ch; +} + +.tools-page:not(.tools-page--single) .content > p:first-child { + font-size: 1.125rem; + line-height: 1.6; +} + +.tools-page:not(.tools-page--single) .content h2 { + font-size: 1.75rem; + font-weight: 700; + margin: 3.5rem 0 0.75rem; + padding-top: 2rem; + border-top: 1px solid #e3e6ea; +} + +.tools-page .content h2, +.tools-page .content h3 { + scroll-margin-top: 140px; +} + +.tools-nav { + position: sticky; + /* Sits directly below the fixed site header */ + top: 78px; + z-index: 900; + background: #fff; + border-bottom: 1px solid #e3e6ea; +} + +.tools-nav ul { + display: flex; + gap: 0.5rem 1.75rem; + margin: 0; + padding: 0; + list-style: none; + overflow-x: auto; + white-space: nowrap; +} + +.tools-nav a { + display: block; + padding: 0.9rem 0; + color: #114b7c; + font-weight: 500; + text-decoration: none; + border-bottom: 2px solid transparent; +} + +.tools-nav a:hover, +.tools-nav a:focus-visible { + border-bottom-color: #d17128; +} + +/* Tool rows: horizontal cards used by the "featured" and "compact" tool-grid variants */ +.tool-rows { + display: grid; + gap: 1.25rem; + margin: 1.5rem 0; +} + +.tool-rows--featured { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.tool-row { + position: relative; + display: flex; + gap: 1rem; + align-items: flex-start; + padding: 1.25rem; + background: #fff; + border: 1px solid #e3e6ea; + border-radius: 8px; + transition: box-shadow 0.2s ease, border-color 0.2s ease; +} + +.tool-row:hover, +.tool-row:focus-within { + border-color: #114b7c; + box-shadow: 0 4px 12px -4px rgba(17, 75, 124, 0.25); +} + +.tool-row__logo { + flex: 0 0 72px; + width: 72px; + height: 72px; + display: flex; + align-items: center; + justify-content: center; +} + +.tool-row__logo img { + max-width: 100%; + max-height: 100%; + width: auto; + height: auto; + object-fit: contain; + border-radius: 6px; +} + +.tool-row__body { + display: flex; + flex-direction: column; + align-self: stretch; + min-width: 0; + flex: 1; +} + +.tool-row__meta { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + margin: 0 0 0.35rem !important; + font-size: 0.75rem; + line-height: 1.4; +} + +.tool-row__task { + color: #585c67; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.tool-row__tech { + padding: 0.1rem 0.5rem; + color: #114b7c; + background: #e8f1f8; + border-radius: 999px; + font-weight: 500; +} + +.content .tool-row__title { + margin: 0 0 0.35rem; + font-size: 1.2rem; + font-weight: 600; +} + +.tools-page .content a.tool-row__link { + color: #114b7c !important; +} + +/* Makes the whole card a link to the tool page */ +.tool-row__link::after { + content: ""; + position: absolute; + inset: 0; + border-radius: 8px; +} + +.content .tool-row__desc { + margin: 0 0 0.75rem; + color: #4a4e58; + font-size: 0.95rem; + line-height: 1.5; +} + +.tool-row__install { + position: relative; + z-index: 1; + align-self: flex-start; + max-width: 100%; + margin-bottom: 0.9rem; + padding: 0.3rem 0.6rem; + overflow-x: auto; + white-space: nowrap; + color: #171b26; + background: #f3f5f7; + border-radius: 4px; + font-size: 0.8125rem; +} + +.tool-row__actions { + position: relative; + z-index: 1; + display: flex; + align-items: center; + gap: 1rem; + margin-top: auto; + align-self: flex-start; + font-size: 0.875rem; + font-weight: 500; +} + +.tools-page .content a.tool-row__docs { + padding: 0.4rem 1rem; + color: #fff !important; + background: #114b7c; + border-radius: 4px; +} + +.tools-page .content a.tool-row__docs:hover { + background: #0d3a61; + text-decoration: none !important; +} + +.tools-page .content a.tool-row__source { + padding: 0.4rem 0; + color: #4a4e58 !important; +} + +.tools-page .content a.tool-row__source:hover { + color: #114b7c !important; +} + +/* Compact rows: a denser list for secondary tools, grouped into columns */ +.tool-columns { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 2rem; + align-items: start; + margin-top: 1.5rem; +} + +.content .tool-group__title { + margin: 0; + font-size: 1.125rem; + font-weight: 700; +} + +.tool-rows--compact { + gap: 0.75rem; + margin: 1rem 0 0; +} + +.tool-rows--compact .tool-row { + padding: 0.9rem 1rem; + gap: 0.85rem; +} + +.tool-rows--compact .tool-row__logo { + flex-basis: 48px; + width: 48px; + height: 48px; +} + +.content .tool-rows--compact .tool-row__title { + font-size: 1rem; +} + +.content .tool-rows--compact .tool-row__desc { + margin-bottom: 0.5rem; + font-size: 0.875rem; +} + +.tools-page .content .tool-rows--compact a.tool-row__docs { + padding: 0.4rem 0; + color: #114b7c !important; + background: none; +} + +.tools-page .content .tool-rows--compact a.tool-row__docs:hover { + text-decoration: underline !important; +} + +@media (max-width: 1199px) { + .tool-rows--featured { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 991px) { + .tool-columns { + grid-template-columns: 1fr; + } +} + +@media (max-width: 767px) { + .tool-rows--featured { + grid-template-columns: 1fr; + } + .hero--compact { + height: 190px !important; + } +} + /* Training Materials pages */ a.next-page-btn { background-color: white; diff --git a/content/tools/core/_index.md b/content/tools/core/_index.md index 3759f67..495a832 100644 --- a/content/tools/core/_index.md +++ b/content/tools/core/_index.md @@ -1,26 +1,31 @@ --- title: "Core NWB Tools" description: "Glossary of Core NWB Tools" +page_nav: + - name: "Start here" + anchor: "start-here" + - name: "Extending NWB" + anchor: "extending-nwb" + - name: "Schemas & specification" + anchor: "schemas-specification" + - name: "Core development" + anchor: "core-development" --- -The glossary shown here provides a quick overview of the key software packages of the core NWB software stack. For a more general discussion of the overall organization of the core NWB software stack see the [NWB Software Ecosystem](https://www.nwb.org/nwb-software) page on the main NWB website. +The core NWB tools are the software packages maintained by the NWB team for reading, writing, converting, validating, and extending NWB data. For how the pieces fit together, see the [NWB Software Ecosystem](/nwb-software/) overview. -## Read/Write NWB File APIs +## Start here {#start-here} -{{< tool-grid category="read-write-api" >}} +Most people need only these. Pick the API for your language to read and write NWB files, use NeuroConv or NWB GUIDE to convert existing data, and run NWB Inspector before you share a file. -## Converting Data to NWB +{{< tool-grid category="read-write-api,data-conversion,validation" variant="featured" >}} -{{< tool-grid category="data-conversion" >}} +## For extension authors and developers {#advanced} -## Validating NWB Files +Tools for extending the NWB standard, the schemas that define it, and the libraries the core APIs are built on. -{{< tool-grid category="validation" >}} - -## Extending NWB - -{{< tool-grid category="extension" >}} - -## Core Development - -{{< tool-grid category="core-development" >}} +{{< tool-columns >}} +{{< tool-grid category="extension" variant="compact" title="Extending NWB" id="extending-nwb" >}} +{{< tool-grid category="schema" variant="compact" title="Schemas & specification" id="schemas-specification" >}} +{{< tool-grid category="core-development" variant="compact" title="Core development" id="core-development" >}} +{{< /tool-columns >}} diff --git a/content/tools/core/aqnwb.md b/content/tools/core/aqnwb.md index 4a1d300..98f70ae 100644 --- a/content/tools/core/aqnwb.md +++ b/content/tools/core/aqnwb.md @@ -6,6 +6,8 @@ image: "/images/aqnwb_logo.png" source_url: "https://github.com/NeurodataWithoutBorders/aqnwb" docs_url: "https://nwb.org/aqnwb/" weight: 25 +task: "Read & write" +tech: "C++" --- ## Description diff --git a/content/tools/core/hdmf-common-schema.md b/content/tools/core/hdmf-common-schema.md index d5ceca6..87426f3 100644 --- a/content/tools/core/hdmf-common-schema.md +++ b/content/tools/core/hdmf-common-schema.md @@ -1,7 +1,7 @@ --- title: "HDMF Common Schema" description: "Schema of common, general data structures used throughout the NWB Standard Schema" -category: "extension" +category: "schema" image: "/images/hdmf_common_schema_logo_framed.png" source_url: "https://github.com/hdmf-dev/hdmf-common-schema" docs_url: "https://hdmf-common-schema.readthedocs.io/en/stable/" diff --git a/content/tools/core/hdmf-specification-language.md b/content/tools/core/hdmf-specification-language.md index a916b82..baeed13 100644 --- a/content/tools/core/hdmf-specification-language.md +++ b/content/tools/core/hdmf-specification-language.md @@ -1,7 +1,7 @@ --- title: "HDMF Specification Language" description: "Formal structures for describing the organization of complex data" -category: "extension" +category: "schema" image: "/images/specification_language_logo_framed.png" source_url: "https://github.com/hdmf-dev/hdmf-schema-language" docs_url: "https://hdmf-schema-language.readthedocs.io/en/latest/" diff --git a/content/tools/core/matnwb.md b/content/tools/core/matnwb.md index 54ddb68..c81bb70 100644 --- a/content/tools/core/matnwb.md +++ b/content/tools/core/matnwb.md @@ -6,6 +6,8 @@ image: "/images/matnwb_logo_framed.png" source_url: "https://github.com/NeurodataWithoutBorders/matnwb/" docs_url: "https://matnwb.readthedocs.io/" weight: 20 +task: "Read & write" +tech: "MATLAB" --- ## Description diff --git a/content/tools/core/neuroconv.md b/content/tools/core/neuroconv.md index dbf9deb..488f304 100644 --- a/content/tools/core/neuroconv.md +++ b/content/tools/core/neuroconv.md @@ -6,6 +6,9 @@ image: "/images/nwbconversiontools_logo_framed.png" source_url: "https://github.com/catalystneuro/neuroconv" docs_url: "https://neuroconv.readthedocs.io/en/main/index.html" weight: 30 +task: "Convert" +tech: "Python" +install: "pip install neuroconv" --- ## Description diff --git a/content/tools/core/nwb-guide.md b/content/tools/core/nwb-guide.md index fdba941..bbed296 100644 --- a/content/tools/core/nwb-guide.md +++ b/content/tools/core/nwb-guide.md @@ -6,6 +6,8 @@ image: "/images/guide_logo_framed.png" source_url: "https://github.com/NeurodataWithoutBorders/nwb-guide" docs_url: "https://nwb-guide.readthedocs.io/en/stable/" weight: 40 +task: "Convert" +tech: "Desktop app" --- ## Description diff --git a/content/tools/core/nwb-schema.md b/content/tools/core/nwb-schema.md index e842861..e728706 100644 --- a/content/tools/core/nwb-schema.md +++ b/content/tools/core/nwb-schema.md @@ -1,7 +1,7 @@ --- title: "NWB Schema" description: "The NWB data standard format specification" -category: "extension" +category: "schema" image: "/images/nwbschema_logo_framed.png" source_url: "https://github.com/NeurodataWithoutBorders/nwb-schema" docs_url: "https://nwb-schema.readthedocs.io/en/latest/" diff --git a/content/tools/core/nwbinspector.md b/content/tools/core/nwbinspector.md index d96f499..44a7a6f 100644 --- a/content/tools/core/nwbinspector.md +++ b/content/tools/core/nwbinspector.md @@ -6,6 +6,9 @@ image: "/images/nwbinspector_logo_framed.png" source_url: "https://github.com/NeurodataWithoutBorders/nwbinspector" docs_url: "https://nwbinspector.readthedocs.io/" weight: 50 +task: "Validate" +tech: "Python ยท CLI" +install: "pip install nwbinspector" --- ## Description diff --git a/content/tools/core/pynwb.md b/content/tools/core/pynwb.md index eb23b29..ff94516 100644 --- a/content/tools/core/pynwb.md +++ b/content/tools/core/pynwb.md @@ -6,6 +6,9 @@ image: "/images/pynwb_logo_framed.png" source_url: "https://github.com/NeurodataWithoutBorders/pynwb/" docs_url: "https://pynwb.readthedocs.io/en/stable/" weight: 10 +task: "Read & write" +tech: "Python" +install: "pip install pynwb" --- ## Description diff --git a/hugo.yaml b/hugo.yaml index df8463b..2eed56b 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -24,3 +24,6 @@ module: mounts: - source: assets target: assets + # Lets templates resize images kept under static/images (see partials/tools/image.html) + - source: static/images + target: assets/images diff --git a/layouts/partials/tools/image.html b/layouts/partials/tools/image.html new file mode 100644 index 0000000..5eb037b --- /dev/null +++ b/layouts/partials/tools/image.html @@ -0,0 +1,16 @@ +{{- /* + Renders a tool image, downscaled to fit the given box and converted to WebP + when the source is a PNG or JPEG under static/images (mounted as assets). + Anything else (GIF, SVG, remote URL) is emitted unchanged. + + Params: page (the tool page), fit (e.g. "640x400") +*/ -}} +{{- $src := .page.Params.image -}} +{{- $alt := .alt | default "" -}} +{{- $img := resources.Get (strings.TrimPrefix "/" $src) -}} +{{- if and $img (in (slice "png" "jpeg") $img.MediaType.SubType) -}} + {{- $small := $img.Fit (printf "%s webp" .fit) -}} + {{ $alt }} +{{- else -}} + {{ $alt }} +{{- end -}} diff --git a/layouts/shortcodes/tool-columns.html b/layouts/shortcodes/tool-columns.html new file mode 100644 index 0000000..5d33794 --- /dev/null +++ b/layouts/shortcodes/tool-columns.html @@ -0,0 +1,4 @@ +{{- /* Lays out the titled tool-grid groups nested inside it as side-by-side columns. */ -}} +
+ {{ .Inner }} +
diff --git a/layouts/shortcodes/tool-grid.html b/layouts/shortcodes/tool-grid.html index 68dad5f..4c66aaa 100644 --- a/layouts/shortcodes/tool-grid.html +++ b/layouts/shortcodes/tool-grid.html @@ -1,11 +1,29 @@ +{{- /* + Lists the tools in one or more categories. + + Params: + category one category, or several separated by commas + variant "card" (default), "featured" or "compact" + title optional heading rendered above the group + id optional id for that heading (defaults to the anchorized title) +*/ -}} +{{- $categories := split (.Get "category") "," -}} +{{- $variant := .Get "variant" | default "card" -}} +{{- $title := .Get "title" -}} +{{- /* Rows sit one level below the heading that introduces them. */ -}} +{{- $heading := cond (ne $title "") "h4" "h3" -}} +{{- $tools := where (where .Site.RegularPages "Section" "tools") "Params.category" "in" $categories -}} +{{ if $title }} +
+

{{ $title }}

+{{ end }} +{{ if eq $variant "card" }}
- {{ $category := .Get "category" }} - {{ range where .Site.RegularPages "Section" "tools" }} - {{ if eq .Params.category $category }} + {{ range $tools }}
{{ if .Params.image }}
- {{ .Title }} + {{ partial "tools/image.html" (dict "page" . "fit" "640x400" "alt" .Title) }}
{{ end }}
@@ -26,6 +44,44 @@

{{ .Title }}

- {{ end }} {{ end }} +{{ else }} +
+ {{ range $tools }} + {{ $tool := . }} +
+ {{ if .Params.image }} + + {{ end }} +
+ {{ if and (eq $variant "featured") (or .Params.task .Params.tech) }} +

+ {{ with .Params.task }}{{ . }}{{ end }} + {{ with .Params.tech }}{{ . }}{{ end }} +

+ {{ end }} + {{ printf `<%s class="tool-row__title">` $heading | safeHTML }}{{ .Title }}{{ printf `` $heading | safeHTML }} +

{{ .Params.description }}

+ {{ if eq $variant "featured" }} + {{ with .Params.install }}{{ . }}{{ end }} + {{ end }} +
+ {{ with .Params.docs_url }} + Docs: {{ $tool.Title }} + {{ end }} + {{ with .Params.source_url }} + Source: {{ $tool.Title }} + {{ end }} +
+
+
+ {{ end }} +
+{{ end }} +{{ if $title }} +
+{{ end }} diff --git a/layouts/tools/list.html b/layouts/tools/list.html index bff2075..38e0e75 100644 --- a/layouts/tools/list.html +++ b/layouts/tools/list.html @@ -1,7 +1,7 @@ {{ define "main" }} {{/* Hero Section */}} -
-

{{ .Title | markdownify }}

+
+

{{ .Title | markdownify }}

@@ -9,7 +9,18 @@

{{ .Title | markdownify {{/* End Hero Section */}} {{/* Content Section */}} -
+{{ with .Params.page_nav }} + +{{ end }} +
{{ .Content }} diff --git a/layouts/tools/single.html b/layouts/tools/single.html index 3c9f5aa..57ad299 100644 --- a/layouts/tools/single.html +++ b/layouts/tools/single.html @@ -9,7 +9,7 @@

{{ .Title | markdownify {{/* End Hero Section */}} {{/* Tool Content Section */}} -
+
From b1e32d4594d529c1cb7b5fb45aac728fb876beca Mon Sep 17 00:00:00 2001 From: Benjamin Dichter Date: Sun, 11 Oct 2026 10:14:01 -0400 Subject: [PATCH 2/2] Use the shorter page banner across the site Every interior page banner now sizes to its title (230px minimum, down from a fixed 350px) and scales the title on small screens. The homepage hero is unchanged. Replaces the tools-only hero--compact class. Co-Authored-By: Claude Opus 5.5 --- assets/css/style.css | 45 +++++++++++++++-------------------------- layouts/tools/list.html | 4 ++-- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 709ac4d..4930cd5 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -321,10 +321,6 @@ } /* Global */ -.hero { - height: 350px !important; -} - .section { padding: 100px 0 !important; } @@ -575,8 +571,17 @@ header { /* Home */ /* Hero */ -.hero { - height: 350px !important; +/* Page banner: sized to its title, with room on top for the fixed site header */ +.hero:not(.homeHero) { + height: auto !important; + min-height: 230px; + padding: 100px 1rem 40px; + overflow: hidden; +} + +.hero:not(.homeHero) h1 { + font-size: clamp(2rem, 7vw, 3rem) !important; + margin-bottom: 0; } .homeHero { @@ -1239,18 +1244,7 @@ ol.custom-ordered-list li::before { } } -/* Tools pages: compact hero, in-page nav, readable intro */ -.hero--compact { - height: 230px !important; - overflow: hidden; -} - -.hero--compact h1 { - font-size: clamp(2rem, 7vw, 3rem) !important; - margin: 2.5rem 0 0 !important; - padding: 0 1rem; -} - +/* Tools pages: in-page nav, readable intro */ .tools-page.section { padding-top: 48px !important; } @@ -1531,12 +1525,13 @@ ol.custom-ordered-list li::before { } @media (max-width: 767px) { + .hero:not(.homeHero) { + min-height: 190px; + padding: 90px 1rem 30px; + } .tool-rows--featured { grid-template-columns: 1fr; } - .hero--compact { - height: 190px !important; - } } /* Training Materials pages */ @@ -1556,10 +1551,6 @@ a.next-page-btn:hover { padding: 60px 0 !important; } -.community-gallery .hero { - height: 300px !important; -} - .community-gallery .section:first-of-type { padding: 40px 0 !important; } @@ -1569,10 +1560,6 @@ a.next-page-btn:hover { padding: 40px 0 !important; } - .community-gallery .hero { - height: 250px !important; - } - .community-gallery .section:first-of-type { padding: 30px 0 !important; } diff --git a/layouts/tools/list.html b/layouts/tools/list.html index 38e0e75..f505d3d 100644 --- a/layouts/tools/list.html +++ b/layouts/tools/list.html @@ -1,7 +1,7 @@ {{ define "main" }} {{/* Hero Section */}} -
-

{{ .Title | markdownify }}

+
+

{{ .Title | markdownify }}