Thank you for your interest in contributing to @behindthemusictree/app-kit!
This package is consumed by grow-the-music-tree-frontend and hear-the-music-tree-frontend.
Changes here affect both apps, so please keep that blast radius in mind.
Contributors can submit bug reports/feature requests via GitHub Issues, open pull requests, improve documentation, and participate in discussions.
Maintainers review and merge pull requests, cut releases, and manage the publish workflow
(.github/workflows/publish.yml, which holds the NPM_TOKEN used to publish to GitHub
Packages).
git clone https://github.com/YOUR-USERNAME/app-kit.git
cd app-kitMaintainers can clone directly:
git clone https://github.com/BehindTheMusicTree/app-kit.git
cd app-kitRequirements:
- Node.js 20.x or higher
- pnpm (see
packageManagerinpackage.jsonfor the pinned version) - A GitHub personal access token with
read:packagesscope, configured for the@behindthemusictreescope againsthttps://npm.pkg.github.com— required to install@behindthemusictree/genre-tree-view, a private dependency of this package.
pnpm installThis repo follows strict Gitflow:
main— always reflects the latest released version. Every commit onmainis tagged (vX.Y.Z). Nothing merges here exceptrelease/*andhotfix/*branches. This is also the GitHub default branch's sibling of record for releases, but PRs targetdevelopby default.develop— integration branch, always reflects the latest delivered development changes. Allfeature/*,fix/*, andchore/*branches are cut fromdevelopand merged back intodevelop. This is the GitHub default branch — PRs target it unless noted otherwise.feature/<short-description>,fix/<short-description>,chore/<short-description>— branch fromdevelop, merge back intodevelopvia PR.release/<version>— branched fromdevelopwhen it's ready to ship (created automatically bypnpm release, see §8). Only version bump and changelog commits belong here. Merged into bothmain(tagged) anddevelop, then deleted.hotfix/<short-description>— branched frommainfor urgent production fixes that can't wait for the nextdevelop→releasecycle (see §9). Merged into bothmain(tagged) anddevelop, then deleted.
main ──●───────────────●───────────────●── (tags only: v1.0.0, v1.1.0, ...)
\ / \ /
release/* ●───●───●───● \ /
/ \ \ /
develop ──●───●───●───●───●───●───●───●──
\ / \
feature/* ●───● ● (fix/*, chore/*)
pnpm dev # tsup --watch on packages/app-kit + apps/playground running in parallelapps/playground is a small Vite app for manually exercising exported components — use it to
sanity-check UI changes before opening a PR.
Generic, stateless UI primitives (Button, Input, Table, ...) live in
@behindthemusictree/ui, not in this package. This
package consumes @behindthemusictree/ui to build its business-logic modules (popup,
genre-tree, ...); it should not grow new generic UI components of its own.
When adding a new module, export it from both its own barrel (src/<module>/index.ts) and the
root barrel (src/index.ts), and add a matching subpath entry to tsup.config.ts and the
exports map in packages/app-kit/package.json.
pnpm build # tsup: ESM + CJS + .d.ts for every entry point
pnpm lint # tsc --noEmit across the workspaceBoth must pass before opening a PR. There is no test suite yet — until one exists, pnpm build
(which runs the DTS build) is the primary type-safety check.
Use Conventional Commits (feat:, fix:, chore:,
docs:, refactor:) — the release script's changelog entries and the semver bump both key off
the change being clearly described.
- Ensure
pnpm build && pnpm lintpass locally. - Open a PR against
developdescribing what changed and why (never againstmain— see §3). - Add a bullet to
CHANGELOG.mdunder[Unreleased]for any user-facing change (new export, behavior change, breaking change). Breaking changes (removed/renamed export, changed prop or function signature, dropped default) go under a### Breakingheading, not### Changed.
From a clean, up-to-date develop:
pnpm release -- patch # or minor / majorThis creates a release/X.Y.Z branch off develop, bumps packages/app-kit/package.json's
version, moves the CHANGELOG.md [Unreleased] section under the new version heading, commits,
pushes the branch, and opens two PRs: release/X.Y.Z → main and release/X.Y.Z → develop.
Once the main PR is reviewed and merged, check out main, pull, and run:
pnpm tag-releaseThis tags the merge commit vX.Y.Z and pushes the tag, which triggers
.github/workflows/publish.yml to build and publish @behindthemusictree/app-kit to GitHub
Packages. Then merge the companion PR into develop (the release branch itself isn't deleted by
either merge, so both PRs stay valid regardless of merge order).
For an urgent fix to what's already released, without pulling in unreleased develop work:
git checkout -b hotfix/<short-description> main
# fix, commit, add a CHANGELOG.md entryPush the hotfix branch and open two PRs, same pattern as §8:
hotfix/<short-description> → main and hotfix/<short-description> → develop. Once the
main PR merges, check out main, pull, and run pnpm tag-release (tag vX.Y.Z per
semver — typically a patch bump) to push the tag and trigger the publish
workflow, then merge the companion develop PR. There is no script to cut the hotfix branch
itself yet — create it with plain git checkout -b.
apps/playground is deployed to Vercel for PR previews. Its .npmrc requires NPM_TOKEN to
install the private @behindthemusictree/genre-tree-view dependency from GitHub Packages —
without it, Vercel builds fail with ERR_PNPM_TARBALL_URL_MISMATCH. Because Vercel doesn't read
repo secrets directly, NPM_TOKEN is pushed into the Vercel project's env vars via
.github/workflows/vercel-playground-env.yml (workflow_dispatch only — not run automatically).
Configure once in the repo's GitHub settings:
| Name | Kind | Value |
|---|---|---|
VERCEL_TOKEN |
Secret | Vercel token with env-write access to the app-kit-playground project |
GH_PACKAGES_TOKEN_READ |
Secret | GitHub Packages read token (same one validate.yml uses); synced to Vercel as NPM_TOKEN |
VERCEL_PROJECT_ID |
Variable | Vercel project id for app-kit-playground |
VERCEL_TEAM_ID |
Variable | Vercel team id (only if the project lives under a Vercel team) |
VERCEL_TOKEN's value comes from a token created under Vercel → Account Settings → Tokens. Name
it app-kit-playground-env-sync there so it's identifiable (and revocable) among other tokens on
the account, then paste the value into the VERCEL_TOKEN GitHub secret above.
To (re-)sync after rotating any of the above: Actions → "Sync playground env to Vercel" → Run workflow. Re-run or push a new commit to pick up the synced token on subsequent deployments.
By contributing, you agree your contributions are licensed under this repository's LICENSE.