No description
  • TypeScript 73.8%
  • SCSS 13.2%
  • JavaScript 12%
  • CSS 0.7%
  • Dockerfile 0.1%
Find a file
Dennis deda0321e8
Some checks failed
Quality / app (push) Has been cancelled
(c) Version 1.2.0-beta.1
2026-11-04 05:45:48 +00:00
.forgejo/workflows (c Deployment version scheme 2026-10-29 09:55:42 +00:00
.github/workflows chore(deps): update app and toolchain to current stable releases 2026-10-26 17:04:38 +00:00
.idea feat(legal): markdown templates with build-time reversal, SPDX headers, English README 2026-10-24 20:28:07 +00:00
.vscode (c) chmod 2025-06-08 12:15:19 +02:00
backend (c) login notification by token 2026-11-04 06:45:07 +01:00
containers (c) deployment fixes 2026-10-27 01:04:01 +00:00
deploy-config docs: make agent onboarding and deployment self-contained 2026-10-26 12:50:30 +00:00
docs (c) login notification by token 2026-11-04 06:45:07 +01:00
frontend-checks@259e5b8c41 (f) updated submodule 2026-10-29 10:46:42 +01:00
messages (f) more detailed error message on opening error 2026-11-02 16:08:26 +00:00
project.inlang build: enforce release checks and bound test memory 2026-10-26 12:50:27 +00:00
public fix(release): include original notices for bundled assets 2026-10-26 07:29:07 +00:00
scripts (c Deployment version scheme 2026-10-29 09:55:42 +00:00
src (c) login notification by token 2026-11-04 06:45:07 +01:00
test (c) login notification by token 2026-11-04 06:45:07 +01:00
third-party chore(deps): update app and toolchain to current stable releases 2026-10-26 17:04:38 +00:00
.env.template docs: make agent onboarding and deployment self-contained 2026-10-26 12:50:30 +00:00
.gitignore (+) deployment 2026-10-26 21:00:01 +01:00
.gitmodules feat(legal): markdown templates with build-time reversal, SPDX headers, English README 2026-10-24 20:28:07 +00:00
AGENTS.md (c Deployment version scheme 2026-10-29 09:55:42 +00:00
Demojahr.zurnote (+) Demodata 2026-10-29 09:45:06 +00:00
flake.lock (c) less pocketbase login notifications 2026-11-02 14:52:01 +01:00
flake.nix (+) deployment 2026-10-26 21:00:01 +01:00
frontend-checks.config.mjs fix(ui): align actions, landmarks and supported theme 2026-10-26 07:23:11 +00:00
index.html fix(release): include original notices for bundled assets 2026-10-26 07:29:07 +00:00
LICENSE feat: add GPLv3 LICENSE and SPDX headers 2026-10-24 10:00:33 +00:00
mise.toml (c Deployment version scheme 2026-10-29 09:55:42 +00:00
package.json (c) Version 1.2.0-beta.1 2026-11-04 05:45:48 +00:00
playwright.config.ts build: enforce release checks and bound test memory 2026-10-26 12:50:27 +00:00
pnpm-lock.yaml fix(a11y): name table fields and verify course views with axe 2026-10-26 17:40:16 +00:00
pnpm-workspace.yaml build(vm): keep package cache on disk and skip test codegen 2026-10-26 17:03:37 +00:00
README.md (c Deployment version scheme 2026-10-29 09:55:42 +00:00
renovate.json (+) deployment 2026-10-26 21:00:01 +01:00
tsconfig.json (f) types 2026-08-25 03:08:24 +02:00
tsconfig.node.json build(types): check tooling configuration explicitly 2026-10-26 12:52:31 +00:00
vite.config.ts build(vm): keep package cache on disk and skip test codegen 2026-10-26 17:03:37 +00:00

ZurNote.de

Client-side encrypted grade management web application built with SolidJS and TypeScript. Currently only focused on german grading systems (KMK / Linear) but you can use it for every grading system by providing your own grading table / formula.

Preview

These recordings show a fictional demo grade book on the local test server. All names, email addresses, assessments and results are made-up sample data.

Manage students and courses

Student list with twelve fictional students and their course assignments

View grades and weights at a glance – written and oral assessments, assessment sheets and calculated overall grades in a single matrix.

Overall grade matrix with weighted categories and KMK grade points

Grade using criteria – award points, apply correction marks and provide individual feedback in an assessment sheet; results can be linked to the grade list.

Completed assessment sheet for a fictional presentation about databases

Choose a grading system – linear grades, KMK grade points, custom lookup tables and formulas. Classroom observation symbols are customizable too.

Course settings with standard grading systems, custom templates and symbol schemes

The workflow walks through opening a class, viewing students, creating an assessment and entering points with automatic grade calculation. It then shows how to create an assessment sheet with sample tasks, grade a student and link the results to the assessments. The workflow ends with the overall grade matrix.

Workflow through the main areas of the demo grade book

Workflow as MP4 · More screenshots and recording instructions

Architecture & Encryption

  • Local storage (IndexedDB): Grade books (classes, courses, students, grades, rubrics, participation, and history) are serialized to JSON, encrypted in the browser with AES-GCM (256-bit) via the Web Crypto API, and stored as binary blobs in IndexedDB.
  • Key derivation: Keys are derived from the user's password using PBKDF2 (SHA-256, 600,000 iterations) and a random 16-byte salt. Decrypted state and keys exist only in memory during an unlocked session.
  • Cloud sync (optional): Synchronizes the encrypted .zurnote binary blob (salt + 12-byte IV + ciphertext) with a PocketBase instance. Only the encrypted payload, book name, and timestamps are stored on the server.
  • Exports: Native backups use .zurnote. Spreadsheet exports (.csv, .xlsx, .ods) are downloaded directly or wrapped in an AES-encrypted .zip archive (@zip.js/zip.js) when a password is set.
  • Legal pages: src/legal/impressum.example.md and src/legal/datenschutz.example.md provide neutral templates. Copy them to src/legal/impressum.md and src/legal/datenschutz.md (gitignored) for production builds.

Development

Tools and tasks are managed with mise (mise.toml), either directly on the host or inside an isolated QEMU MicroVM via nix-dev-sandbox (flake.nix).

Use Node 26.12.1 and pnpm 12.15.0 (mise install installs the pinned tools). Start with AGENTS.md, the architecture and coding standards. The deployment guide and optional backend describe production setup. Asset provenance is in third-party/.

Host

mise run install
mise run dev         # http://127.0.0.1:5273

MicroVM

Configure .env once on the host:

cp .env.template .env   # set DEV_SSH_PUBKEY, GIT_USER_NAME, GIT_USER_EMAIL

~/.ssh/config:

Host zurnote-vm
    HostName 127.0.10.4
    Port 2200
    User dev
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
    IdentityFile ~/.ssh/id_ed25519

Start the VM and run the dev server inside:

nix run --impure
ssh zurnote-vm
mise run install
VITE_HOST=0.0.0.0 mise run dev  # exposed inside the VM and forwarded to the host

The VM's playwright profile provides Chromium from nixpkgs through PLAYWRIGHT_BROWSERS_PATH; do not run playwright install inside the VM. nixpkgs' playwright-driver must have the same version as @playwright/test in package.json. Update both together (nix flake update, then rebuild the VM). Until they match again, point PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH at a Chromium from $PLAYWRIGHT_BROWSERS_PATH.

Tasks

Command Description
mise run install Initialize submodules (frontend-checks) and install dependencies
mise run dev Start Vite dev server on http://127.0.0.1:5273 (fixed port to preserve IndexedDB origin)
mise run check:all Run static frontend checks (@dencla/frontend-checks), TypeScript typecheck, and unit tests
mise run test Run unit tests (Vitest and node --test)
mise run build Compile i18n messages, generate third-party license data, run all checks, and build to dist/
mise run build:demo Build with legal templates for public checkouts and CI; do not publish this artifact
mise run test:e2e Test the existing build in four Chromium viewport sizes
mise run release:prepare <version> Set the SemVer version in package.json, commit it and create tag v<version> (no push)
mise run release:deploy v<version> Require the tag to match package.json and a clean tree, install locked dependencies, check production documents, build/test and prepare the d0b delivery archive
mise run test:containers Build and test both delivery roles with rootless Podman
mise run preview Serve production build on port 4173

Dependency installation is explicit and uses --frozen-lockfile. Checks never reinstall packages. Install the test browser once with pnpm exec playwright install chromium; Linux CI additionally uses --with-deps. pnpm build requires filled local legal documents. A fresh public checkout can use pnpm build:demo, then pnpm test:e2e. The supported appearance is light.

GitHub CI runs the demo build, unit/component checks, browser flows and an isolated PocketBase ownership test. No production book data is used.

License

Copyright 2026 Dennis Burgermeister. Licensed under GPL-3.0-or-later. Bundled third-party assets retain their individual licenses.

Betrieb

Das Deployment auf d0b verwendet den Dienst gradingcloud mit zwei rootless Podman-Rollen: Caddy für die App und PocketBase für die optionale Cloud. Die Version steht nur in package.json; das Release-Tag ist v<version>.

mise run release:prepare 1.0.0-beta.1   # Version setzen, committen, Tag anlegen
mise run release:deploy v1.0.0-beta.1     # prüft Tag = Version, baut und testet
mise run test:containers
git push --follow-tags                  # Forgejo baut das Release aus dem Tag

release:deploy ändert die Version nicht, sondern bricht bei abweichendem Tag oder uncommitteten Änderungen ab, damit Bündel, Commit und angezeigte Version übereinstimmen. mise run release:deploy erstellt das geprüfte Vertrag-1-Bündel; mise run test:containers prüft beide Images. Einrichtung, Secrets, Forgejo- Release und Umzug sind in docs/deployment.md beschrieben.