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.
Use Node 24 and pnpm (the exact pnpm version is pinned in package.json).
pnpm install --frozen-lockfile
pnpm dev
pnpm checkcheck 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 siteCreate 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 othersorand 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. tagsandaudiencesare multiple-choice, contributor-defined taxonomies. Reuse existing spelling/case; whitespace and exact duplicates are normalized. Case is preserved so TeX commands such as\Gammaremain correct.maintenance:active,maintenance-only, orarchived. 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 markedarchived. 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.MITorMIT OR Apache-2.0); custom licenses are allowed.- Affiliations and funding support multiple records. Missing arrays become empty.
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.
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.
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:staticEvery 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.
- 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/(nameis 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 suppliedmath-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.