This is an implementation of the Chemistry Land-surface Atmosphere Soil Slab (CLASS) model that runs entirely in the browser.
The CLASS web application is available at https://classmodel.github.io/class-web.
For more information on CLASS, see https://classmodel.github.io/.
This repository is a so-called monorepo, where multiple packages and application can easily be developed in tandem.
We used TurboRepo for the initial setup, which uses
pnpm workspaces under the hood. As such, it is
possible to do advanced tricks with Turbo, such as "lint/test/build all
apps/packages at once with turbo build
", and share tooling configurations
across packages/apps, but since this repo is small, we will not rely too much on
these features.
Currently the repo is home to the following:
- packages/
- class: reimplementation of CLASS in typescript
- apps/
- class-solid: web application with a graphical user interface for CLASS
The Class model uses a JSON schema to validate the input configuration. The schema is defined in the @classmodel/class
package and can be found in packages/class/src/config.json. The schema is used to validate the input configuration and to generate a form to input the configuration.
If any changes are made to the packages/class/src/config.json
file then the Typescript type need to be regenerated with the following command:
cd packages/class
pnpm json2ts
To run a local development version:
git clone [email protected]:classmodel/class-web.git
cd class-web
pnpm install
pnpm dev
We use biome to lint and format the code. The following commands are available
# To run linter and formatter use
pnpm format-and-lint
# To fix formatting and some lint errors run
pnpm format-and-lint:fix
# To run other biome comands use
pnpm exec biome --help
To check types, you can run the pnpm typecheck
command as other commands ignore types.
The unit tests are written with node:test and node:assert.
The unit tests can be run with the following command:
pnpm test
To get test coverage
# Does not work via pnpm script so need to call node directly
node --import tsx --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info src/*.test.ts
# To generate a html report use genhtml which is part of lcov OS package
genhtml lcov.info --output-directory coverage
The end-to-end tests are written with playwright.
The tests are in apps/class-solid/tests/*.spec.ts
and can be run with the following command:
cd ./apps/class-solid
pnpm exec playwright install # first time only
pnpm exec playwright test
The CLASS package is written in typescript. It uses a JSON schema to define the shape and constraints of a configuration. JSON schema is cross-langanuage and is ideal for sharing the configuration between web-app, library code, and perhaps other implementations of CLASS as well. To validate a configuration it uses the JSON schema together with ajv. Ajv is the reference JSON schema validator in then JS ecosystem.
The web application is build with solid.js. Solid is a relatively simple framework for building reactive web applications. With its metaframework SolidStart it is quite easy to pre-render the web application as static pages that can be hosted on github pages. To keep track of form state and errors it uses modular forms package.
We've chosen SolidUI as the basis for the UI. Build after ShadCN, SolidUI provides good-looking, accessible components (powered by Kobalte and tailwind) that can be copy-pasted into the web application and tweaked further as seen fit. It can also do charts, using chart.js, though we might deviate from that later.
To expose the model in a standard way we use the Basic Model Interface (BMI).
To prevent the user interface from getting blocked by running the model we use a Web worker to run the computation in a background task/thread. A Web worker uses messages passing to communicate, this does not fit with the Basic Model Interface so we use comlink to wrap the Web Worker in a BMI class.
To format and lint the code, we use biome as it combines eslint, prettier in one package.
Further plans/ideas
- Use auto for managing versions/releases
- Use d3.js for more low-level charting
- Use AssemblyScript or rust for a faster implementation of CLASS running on web assembly.
- Use storybook for UI component package