ZAYEED preview
Home / Integrations

Into the VLE without an integration project

Zayeed's server is an LTI 1.3 tool. A teacher places the activity, a student clicks it, and the mark goes back to the gradebook. There is no bespoke connector to commission and no nightly CSV to reconcile.

LTI 1.3

# point the server at a signing key and the platforms it trusts
export ZAYEED_TOOL_URL=https://exams.example.edu   # where the platform reaches the tool
export ZAYEED_APP_URL=https://app.example.edu    # where a launched student lands
export ZAYEED_LTI_KEY=./lti-private.pem         # generated on first use if absent
export ZAYEED_LTI_CONFIG=./lti-platforms.json    # issuer, client id, auth + token URLs

/lti/config describes the tool for a platform administrator and /lti/jwks publishes its public key. The private key never leaves the server, and the gradebook credential never reaches a device.

QTI 3.0

Import and export both run through a dedicated package. Where a construct does not map cleanly in either direction, the item carries a note saying so. Silent loss during an interchange is worse than a refusal, because nobody finds it until the paper has already been sat.

Packs

The .mcq container is the interchange format when there is no network at all: items, media, rules, question sets and the on-screen keyboard layout in one file, encrypted and signed, with a lossless bridge to and from the database. It is specified rather than merely shipped — the specification and its test vectors are published, so a reader can be written from them alone — and every shell still opens the .mcqx ZIP it replaced and the legacy MCQPro banks that came before that, deciding which by reading the bytes.

The same container carries a sync bundle: the changes one device has that another has not seen, rather than a snapshot. Hand it over on a memory stick and it merges into whatever the other machine has done since; apply it twice and the second time changes nothing.

Self-hosting

The server runs on Node against SQLite by default, or Postgres by setting DATABASE_URL. Both are generated from one schema definition and pinned by a parity test, so self-hosting is the same product rather than a reduced edition. For air-gapped estates, the sync server and the shells never require an outbound connection to us.

Still deciding?

The fastest way to judge a marker is to try to break it. Run a paper, answer it badly on purpose, and read the reason next to every mark.