Skip to content

Repository files navigation

Department software directory

A directory of scientific software developed by current and former members of the University of Graz's Department of Mathematics and Scientific Computing. It brings together research tools, community contributions, and historical software, with descriptions, source links, and related publications.

Built with Nuxt 4, Vue, and Tailwind CSS 4, the site is fully static and requires no deployed backend. Project entries are maintained in Markdown with YAML metadata; publications are stored in BibTeX. The responsive design uses the Graz mathematics badge, yellow accents, and self-hosted Noto Sans.

Development

Use Node 24 and pnpm (the exact pnpm version is pinned in package.json).

pnpm install --frozen-lockfile
pnpm dev
pnpm check

check runs unit tests, typechecking, static generation, and a small output smoke check. No browser-test framework is required. A local Nuxt module compiles content at startup; changes under content/ are watched to restart development. If your editor's filesystem events are missed, restart pnpm dev.

pnpm generate           # deploy .output/public, not .output/server
pnpm preview            # preview the generated site

Adding a project

Create content/projects/my-project.md. The filename is the permanent URL slug: /projects/my-project/. Use lowercase words separated by hyphens. Changing it changes the URL; there are currently no automatic redirects.

---
name: 'My solver for $L^2$ problems'
summary: 'An efficient solver for $L^2$ approximation problems.'
source:
  url: https://github.com/example/solver
  # doi: 10.1234/example
authors:
  - name: Ada Example
authorsNote: and others
tags: [numerical analysis]
audiences: [research, industry]
publications: [] # Add keys from content/publications.bib
funding:
  - funder: Example funder
    grant: EXAMPLE-123
    url: https://example.org/grant
affiliations:
  - title: L2SOLV Research Project
    url: https://www.example.at/l2solv-project-url/
license: MIT
docs: https://example.org/docs
maintenance: active
---

Optional Markdown description, with inline $x^2$ or display math:

$$
\int_\Omega u(x)\,dx.
$$

Only name, source, and a non-empty authors list are required. Each author has a name and may have an orcid URL. At least one of source.url and source.doi must point to the software/source code, not a related paper. Both are allowed. DOI URLs are normalized to bare identifiers.

All other fields are optional. Unknown fields, blank required values, unsafe URLs, invalid maintenance states, bad slugs, and unresolved publication references fail the build. Errors identify the source file. See scripts/schema.ts for the exact schema. Existing files under content/projects/ provide working examples.

  • summary: optional description of one or two sentences, written for directory cards. It is also used as the detail page's plain-text SEO description; the Markdown body remains the full description. Summaries are not automatically truncated.
  • authorsNote: optional text appended after the named authors on both cards and detail pages, e.g. and others or and the Manim community. Include the desired conjunction/punctuation; a separating space is added automatically. This note acknowledges partial author lists without adding a fictitious author or altering publication credits.
  • Both fields support inline math like name, not Markdown formatting or raw HTML. Omit unused fields rather than leaving them blank. Both are included in search.
  • tags and audiences are multiple-choice, contributor-defined taxonomies. Reuse existing spelling/case; whitespace and exact duplicates are normalized. Case is preserved so TeX commands such as \Gamma remain correct.
  • maintenance: active, maintenance-only, or archived. Omission means unspecified, not abandoned. Authors should keep this information current. Historical projects are welcome: for this catalog, software whose last known update predates 2015 can be marked archived. A paper's publication date is not a software update date, and an archived mirror after a repository move does not by itself mean the project is archived.
  • license: free text, preferably an SPDX identifier/expression (e.g. MIT or MIT OR Apache-2.0); custom licenses are allowed.
  • Affiliations and funding support multiple records. Missing arrays become empty.

Publications and mathematics

Add BibTeX entries to content/publications.bib; reference their keys from each project's publications list. Duplicate bibliography keys and missing references are errors. References render in APA style, in the order listed by the project. No DOI metadata lookup or other network fetch happens during content compilation. An entry is rendered only when referenced by a project.

The compiler uses the released @behackl/citation-js-extras@0.2.0 with preserveMath: true, and Citation.js 0.7.22 (the tested version). Keep these compatible when upgrading.

MathJax with the base and AMS packages renders SVG at build time. There is no browser MathJax runtime, external font request, or CDN dependency. The same renderer handles names, authors, tags, affiliations, funding, and publications. URLs/identifiers are not math-rendered. Browser titles/metadata are plain text, not typeset HTML.

  • Markdown body: $...$ inline, $$...$$ in a separate block for display math.
  • Metadata: $...$ or \(...\) for inline math; quote YAML values with single quotes to avoid YAML interpreting backslashes.
  • BibTeX: $...$, $$...$$, \(...\), and \[...\], protected by the extras package.
  • Escape literal dollar signs as \$. Code blocks/spans are not math-rendered.
  • Unsupported TeX produces a build error. Arbitrary LaTeX packages and arbitrary user-defined macros are not supported; renderer configuration lives in scripts/render.ts.

Raw Markdown HTML is disabled. Markdown links and bibliography HTML are sanitized before trusted MathJax output is inserted. Metadata is escaped.

Generated data and filtering

The local module scripts/nuxt-catalog.ts runs the compiler in scripts/catalog.ts and registers typed templates with Nuxt's addTemplate API, under software-catalog/ in Nuxt's build directory:

  • index.ts: project names, authors, optional summaries and author notes (including their rendered inline HTML), normalized searchable description text, filter values, and all available facet options with total counts.
  • projects/<slug>.ts: full rendered project details and bibliography.
  • loaders.ts: an explicit registry of lazy per-project imports.

These are generated build artifacts; do not edit or commit them. The app imports through #build/software-catalog/..., and useAsyncData lets Nuxt serialize the results into its normal SSR/static payloads. There is no catalog HTTP endpoint, filesystem read in application code, or deployed API. This avoids fetching public files through Nitro's internal SSR request handler.

The directory loads the summary index. Detail HTML is lazy-loaded for project pages, not bundled into the index. Search ignores case and accents and requires all search terms to occur across a project's name, authors, author notes, summary, or description. It does not use fuzzy matching. Literal TeX is searchable, but mathematically equivalent expressions are not treated as interchangeable.

The collapsible filter panel exposes Topic, Target audience, and Maintenance (tags, audiences, and maintenance in URLs). Topic uses a searchable multiselect with checkboxes, removable selections, and a Clear button; audience and maintenance retain their compact toggle badges. Searching within the topic picker only narrows its options, not the project search or existing selections. Other facets remain metadata; their legacy URL parameters and unknown options are ignored, never silently applied. Filters use OR within a category, AND between categories. Counts (visible in the topic picker and available to screen readers elsewhere) ignore the category's own selection. Selected filters are yellow; project badges highlight matching selections, not maintenance status itself. Topics use filled pills, audiences use outlined pills with a people icon, and maintenance uses rounded rectangles with status-specific icons (check, wrench, or archive). Unspecified maintenance has a question-mark icon in filters and is omitted from project badges.

Search/filter state is stored in query parameters (repeat a parameter for multiple choices), carried into detail links, and restored by their Back link. “Reset all filters” clears search and selections. On a static host, URL filters are applied after hydration. “Show more” displays 25 additional entries; a complete link list is included for no-JavaScript use.

The index is linear in catalog size and appropriate for hundreds/thousands of entries. No bibliography processor or full description HTML is shipped in the search index. The filter functions in shared/catalog.ts are separate from the UI.

GitHub Pages

Enable Settings → Pages → Build and deployment → Source: GitHub Actions. .github/workflows/pages.yml validates pull requests and builds/deploys main. The workflow uses Node 24 and the pnpm version from package.json. Deployment uses GitHub's Pages artifact and OIDC permissions; no personal access token.

This organization-site repository (unigrazmath.github.io) uses / as its base path. For a project-site deployment set the repository variable NUXT_APP_BASE_URL to /repository-name/ (including both slashes), or locally:

NUXT_APP_BASE_URL=/software/ pnpm generate
NUXT_APP_BASE_URL=/software/ pnpm check:static

Every project is explicitly pre-rendered as projects/<slug>/index.html so direct navigation works without an SPA fallback. /imprint/ is also pre-rendered; .nojekyll and 404.html are included. The catalog module supplies the prerender route list; Nuxt generates the page payloads and bundles the lazy imports. No custom public-asset copy hook is needed.

Design handoff

  • Shared shell: app/layouts/default.vue; header, icons, cards and pill controls: app/components/
  • Topic picker: app/components/SearchableMultiSelect.vue, adapted from the ECMTB 2026 timetable component with local styling and math-rendered labels. Its inline dropdown supports Escape, outside-click dismissal, and native keyboard navigation without teleporting or manual positioning.
  • Directory, project details and imprint: app/pages/ (name is the project title; no separate display identifier)
  • Design tokens, responsive styles and Tailwind/font imports: app/assets/css/main.css
  • Badge: public/branding/math-graz.svg, from the supplied math-graz-profile.svg, with hidden/editor artwork removed and visible paths preserved
  • Fonts: @fontsource-variable/noto-sans; redistributed license: public/fonts/noto-sans-OFL.txt (no Google Fonts/CDN requests)
  • Typed search/filter model: shared/catalog.ts; URL state: app/composables/useDirectoryState.ts
  • Content validation/rendering: scripts/

Rendered HTML (v-html) must only come from the compiler, never directly from query parameters or unvalidated content. Keep labels, focus states, status text, and semantic headings when replacing the visual design.

About

Collection of software projects of the University of Graz' Department of Mathematics and Scientific Computing

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages