PRD — h5pkit Question Bank Registry and Documented Extensions¶
Initiative: INIT-H5PKIT-001
Status: Draft
Home repo: github.com/grokify/h5pkit
Problem¶
h5pkit can build, validate, serialize, and package H5P question content, and
it already carries a small metadata extension (h5pGo) for section, topic,
tags, difficulty, and learning objective. Two things are missing for anyone
who wants to manage questions rather than only author them:
- There is no concept of a question bank. A
QuestionSetis a playable H5P activity, not a curated, versioned, reusable collection with a license and provenance. Consumers that need banks (a learning game, a course platform, an assessment tool) each have to invent their own wrapper, and those wrappers do not interoperate. - The extension is informal. Its namespace reflects a former project
name,
difficultyis a free string, there is no place for skill or standards alignment, and nothing documents the block as something other tools may read or write. Because H5P players ignore unknown data, the block is safe to carry, but it is only useful across tools if its shape is stable and documented.
The preference is to stay inside H5P's own approach wherever H5P has one, and to extend only where it does not, documenting each extension so that other projects can use it independently of any one consumer.
Goals¶
- A storage-agnostic question bank registry in h5pkit: banks, immutable
published versions, licenses, fork and remix lineage, and skill and
standards tags, with a
Storeinterface and an in-memory implementation. No database dependency in h5pkit. - Documented, namespaced extensions for the metadata H5P does not model: relative difficulty, skills, and standards alignment, written so a standard H5P player still imports the content unchanged.
- More native question types in the Go SDK: true/false, fill in the blanks, single choice set, essay, and the drag-based types that cover matching and ordering, so consumers do not invent non-H5P question formats.
- Round-trip interoperability: a bank version exports to a standard
.h5pquestion set, and an imported.h5pbecomes a bank version.
Non-Goals¶
- A persistent (SQL or Ent) store. That belongs to the consuming application
or a separate module, implementing the registry's
Storeinterface. - Mastery, scoring policy, rewards, certificates, or any learner state. The registry describes content, not people.
- A hosted registry service or marketplace. This initiative delivers the library; services are built on it.
- Replacing H5P's per-answer feedback with a custom explanation field. H5P already models feedback natively.
Users and Stakeholders¶
| Who | Needs |
|---|---|
| Application developers building on h5pkit | Bank, version, license, and lineage types they can persist and expose without redesigning them |
| Content authors and educators (through those applications) | Difficulty, skill, and standards metadata that survives export and import |
| Other H5P tooling | A documented extension block they can read or ignore safely |
| h5pkit maintainers | Content types that follow the existing typed-params pattern and the roadmap already published |
Requirements¶
Functional¶
- F1. A
registrypackage definesBank,BankVersion,License,Lineage(parent bank and version for forks and remixes), and tag types for skills and standards. Versions holdh5p.Questionvalues. - F2. A published
BankVersionis immutable; changing content creates a new version. Draft versions may be edited until published. - F3. A
Storeinterface covers create, get, list (with filters by tag, skill, standard, license), new version, publish, and lineage lookup; an in-memory implementation and a reusable conformance test suite ship with it so other stores can prove compatibility. - F4. The metadata extension is renamed to the
h5pkitnamespace. The formerh5pGokey is no longer read or written; no stored content depends on it. - F5. The extension gains
difficultyScore(a relative score within the bank, 0 to 1),skills(identifiers in a named taxonomy), andstandards(framework plus code, for example a Common Core or NGSS reference). The existing free-stringdifficultylabel remains for display. - F6. Extension content is validated: score range, non-empty skill identifiers, standards with both framework and code.
- F7. Typed parameters and builder methods for
H5P.TrueFalse,H5P.Blanks,H5P.SingleChoiceSet,H5P.Essay,H5P.DragText, andH5P.DragQuestion, each validated against its semantics. - F8. A
BankVersionexports to aQuestionSetand to a.h5ppackage; a.h5pquestion set imports to a draftBankVersion, with extension metadata preserved both ways. - F9. The TypeScript editor exposes the extension fields (difficulty score, skills, standards) for the types it already edits.
Non-Functional¶
- N1. Content with the extension block loads in a standard H5P player unchanged; the extension lives beside, not inside, library parameters.
- N2. Every extension field is documented in a guide that stands on its own, without reference to any particular consumer.
- N3. Existing public API is preserved except for the namespace rename in F4, which is called out in release notes.
- N4.
golangci-lintpasses; unit tests cover the registry, the extension validation, each new content type, and round-trip export and import.
Success Criteria¶
- A consumer can create a bank, add questions with difficulty, skill, and
standards metadata, publish a version, fork it into a new bank with
lineage recorded, and export the version as a
.h5pthat a standard H5P player opens. - A second
Storeimplementation (in a consumer) passes the conformance suite without changes to h5pkit. - The six content types in F7 round-trip through JSON and
.h5pwith validation.
Risks¶
| Risk | Mitigation |
|---|---|
| Namespace rename breaks stored content | No content depends on the old key; the release notes name the rename |
| Extension drifts into consumer-specific fields | Keep the block to content metadata; anything about learners or rewards is refused in review |
| Content-type semantics versions move upstream | Pin the library version string per type, as H5P.MultiChoice 1.16 is pinned today, and document the policy |
| Registry grows into a service | Non-goal stated; the Store interface is the boundary |
Decisions¶
- Difficulty is relative within a bank, not absolute. A score of 0.8 in an arithmetic bank is not comparable to 0.8 in a calculus bank; the documentation says so, and no cross-bank scale is implied.
- Standards are references, not a taxonomy. h5pkit records
{framework, code}pairs; it does not ship or validate the frameworks themselves. - Skills use caller-supplied taxonomy identifiers. h5pkit records
{taxonomy, id}; the taxonomy is the consumer's.