Skip to content

Contributing ​

Thanks for helping improve IVKit! Bug reports, ideas and pull requests are all welcome.

Reporting a bug ​

Open an issue with:

  • What you expected and what happened instead.
  • The smallest story that shows the problem. Run it through validateStory first, since many problems are invalid stories.
  • The IVKit version, from npm ls @ivkit/player or VERSION in @ivkit/core.
  • Your browser and operating system, and your framework if you use one.

Setting up ​

You need Node.js 24 and pnpm. Use the pnpm version pinned in package.json, for example through Corepack:

sh
corepack enable
pnpm install --frozen-lockfile

Project layout ​

PathWhat it is
packages/core@ivkit/core: the story format, engine, media controller and validation. No DOM dependencies and no runtime dependencies.
packages/player@ivkit/player: the <ivkit-player> Web Component, built on core.
packages/react@ivkit/react: a React component around the player.
docsThe documentation site, built with VitePress and published to GitHub Pages.
docs/examplesThe live examples. Their stories are in docs/examples/stories.
scriptsChecks for bundle size and package exports, and the publish script.

Commands ​

CommandWhat it does
pnpm typecheckType-checks every package.
pnpm lintChecks formatting and lint rules with Biome.
pnpm formatFormats the code and applies safe lint fixes.
pnpm testRuns every test. Core runs in Node, and the player and React component in happy-dom.
pnpm test:watchRuns the tests in watch mode.
pnpm test:coverageRuns the tests with a coverage report in coverage/.
pnpm buildBuilds every package into its dist folder.
pnpm check:sizeBuilds every package and checks them against their size budgets.
pnpm check:exportsChecks what each runtime resolves from the player's entries, and that the React component stays a client component. Run it after a build.
pnpm docs:devServes the documentation at http://localhost:5173/ivkit/.
pnpm docs:buildBuilds the documentation site.

CI runs lint, typecheck, test:coverage, check:size and check:exports on every pull request.

Size budgets ​

The library is meant to stay small, so pnpm check:size fails when a build grows past its budget:

BuildGzip budget
Standalone player, including core and CSS9.5 KiB
All of core6 KiB
StoryEngine only2 KiB
validateStory only3 KiB

The player, core and validation budgets grew by 0.5, 1 and 0.25 KiB for variables and conditions, which are part of the story format and so belong in core rather than in a plugin. Multiple-answer questions, also part of the format, added 0.5 KiB to the player and core and 0.25 KiB to the engine and validation. Question timeouts added another 0.5 KiB to the player and core and 0.25 KiB to validation. Cues and plugin support added 0.25 KiB to the engine and validation, so plugins can build on the format instead of growing it.

It also checks that validation isn't bundled into the player, and that neither package gains a runtime dependency. If a change needs a bigger budget, explain why in the pull request.

Writing code ​

  • Core never touches the DOM. It talks to media through the MediaElement interface, so it can run in Node and be tested with fakes.
  • Keep the player safe to import on the server. Don't use window, document or other browser globals at module level.
  • Test behavior, not implementation. Core tests drive the engine and controller with fake media. Player tests render the element in happy-dom.
  • Document public changes. Update the guide or reference page for any change to the story format or the public API, and add an entry to CHANGELOG.md under Unreleased.

Documentation and examples ​

The documentation is in docs, as Markdown. Pages are written in English, with short sentences and a code example for each feature.

The live examples use placeholder clips, so that hotspots line up exactly with what's drawn in the video. If you replace a clip, keep the hotspots in docs/examples/stories in sync.

Pull requests ​

  1. Create a branch from main.
  2. Make your change, with tests.
  3. Run pnpm typecheck, pnpm test and pnpm check:size.
  4. Write commit messages in the Conventional Commits style used in this repository, such as feat(player): …, fix(core): … or docs: ….
  5. Open a pull request that explains what changed and why.

Releasing ​

Maintainers release every package together, with the same version. Publishing is automated: creating a GitHub release runs the release workflow, which runs every check and publishes to npm through trusted publishing, with provenance and no npm token.

  1. In a pull request, set version in the package.json of packages/core, packages/player and packages/react, and move the Unreleased entries in CHANGELOG.md into a section for the new version, with its compare link.

  2. After it's merged, create the GitHub release from main, with that version's changelog section as its notes. The tag must be v plus the version:

    sh
    gh release create v0.1.2 --target main --title v0.1.2 --notes-file notes.md

    For a prerelease such as 1.0.0-beta.1, add --prerelease. It's published under npm's next tag, so it's never installed by default.

  3. Follow the Release run under Actions. If a step fails, fix the cause and re-run the workflow. Versions already on npm are skipped.

  4. If jsDelivr still answers 404 for the new version, clear its cache with https://purge.jsdelivr.net/npm/@ivkit/player@<version>/dist/ivkit-player.min.js.

To check what would be published without publishing, run pnpm build and then node scripts/publish.mjs --dry-run.

By contributing, you agree that your contributions are licensed under the project's Apache License 2.0.