Skip to content

Repository files navigation

@galalem

A monorepo of small, focused, open-source React libraries — independently versioned and published to npm under the @galalem scope.


What is this?

This repository is a home for many independent React packages, not a single library. Each package solves one problem well (a component, a hook, a utility), ships on its own version, and can be installed on its own:

npm i @galalem/<package-name>

They live together in one repo so they can share tooling, testing, and a release pipeline — but they are published separately and have no forced coupling. You can install one without dragging in the others.

Philosophy

These principles are the contract. Every package in this repo should honor them, and any change — human or automated — should be evaluated against them.

  • Small and single-purpose. A package does one thing. If it grows two responsibilities, it becomes two packages. Prefer many small packages over one kitchen-sink library.
  • The app owns React, not us. react (and react-dom when needed) are peer dependencies, never regular dependencies. We bind to the single React instance the consuming app already has. A package must never bundle or pin React.
  • Typed by default. Everything is written in TypeScript and ships .d.ts type definitions. The public API is the exported types.
  • ESM-first, dual-format. Every package ships both ESM and CJS builds so it works in modern bundlers and older toolchains, and is tree-shakeable (sideEffects: false unless a package genuinely has side effects, e.g. imported CSS).
  • Publish the build, not the source. Only compiled output (dist/) is published. Source, tests, and config stay in the repo.
  • Tested before shipped. A package without tests is not ready to publish. Behavior is verified with Vitest.
  • Compatible and honest. The supported React range in peerDependencies is a promise we verify in CI against every version we claim — not an aspiration.
  • Independent versioning. Packages version and release on their own cadence via Changesets. One package's release never forces a bump on another.

Repository structure

Packages live under a scope-named folder so the on-disk layout mirrors the npm scope:

react/                         ← this repo (private root, never published)
├── @galalem/                  ← workspace packages; folder name mirrors the npm scope
│   └── <package-name>/        ← one directory per package → publishes as @galalem/<package-name>
│       ├── src/
│       │   └── index.ts       ← the package's public entry point (barrel of exports)
│       ├── package.json       ← name, exports, peerDependencies, build script
│       ├── tsconfig.json      ← extends ../../tsconfig.base.json
│       ├── README.md          ← per-package docs (install, usage, API)
│       └── CHANGELOG.md       ← generated by Changesets — do not edit by hand
├── .changeset/                ← pending release notes + Changesets config
├── .github/workflows/         ← CI (test matrix) and Release (publish) pipelines
├── pnpm-workspace.yaml        ← declares packages live under @galalem/*
├── tsconfig.base.json         ← shared TypeScript settings all packages extend
├── package.json               ← private root: shared devDeps + workspace scripts
└── README.md                  ← you are here

Note on the folder name: the directory is literally named @galalem so the repo path visually matches the published name. npm only cares about the name field inside each package.json — the folder name is cosmetic. A package at @galalem/foo with "name": "@galalem/foo" publishes as @galalem/foo.

Tech stack

Concern Tool
Package manager pnpm workspaces
Language TypeScript
Build (lib bundling) tsup — ESM + CJS + .d.ts
Tests Vitest + React Testing Library
Versioning/publish Changesets
CI/CD GitHub Actions

Prerequisites: Node >=20 and pnpm (corepack enable will provide it).

Getting started

git clone https://github.com/galalem/react.git
cd react
pnpm install          # installs deps for the whole workspace
pnpm build            # builds every package
pnpm test             # runs every package's test suite

Root scripts fan out across all packages via pnpm -r:

Script What it does
pnpm build Build every package (src/dist/).
pnpm test Run every package's tests.
pnpm changeset Record an intended release (run after a change).
pnpm version Apply pending changesets: bump versions + changelogs.
pnpm release Build, then publish changed packages to npm.

The package contract

Every package in @galalem/* must provide the following. This is the checklist a new package is measured against.

package.json with at minimum:

{
  "name": "@galalem/<package-name>",
  "version": "0.0.0",
  "description": "<one sentence>",
  "license": "MIT",
  "type": "module",
  "sideEffects": false,
  "files": ["dist"],                     // only ship the build
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  },
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs --dts --external react",
    "test": "vitest run"
  },
  "peerDependencies": {
    "react": ">=18"                      // widen only to versions CI verifies
  },
  "publishConfig": {
    "access": "public"                   // scoped packages are private by default
  }
}

Also required:

  • src/index.ts — the single public entry point. Everything consumers can use is exported from here; anything not exported here is private.
  • tsconfig.json extending ../../tsconfig.base.json.
  • At least one test file (*.test.ts/*.test.tsx) covering the public behavior.
  • A README.md with install, a usage example, and the public API.
  • React used only via peerDependencies (+ devDependencies for local build/test). Never in dependencies.

Creating a new package

  1. Create @galalem/<package-name>/ following the structure and contract above.
  2. Write src/index.ts and its tests.
  3. From the repo root, pnpm install (links the new package into the workspace).
  4. pnpm --filter @galalem/<package-name> build && pnpm --filter @galalem/<package-name> test.
  5. Add a changeset: pnpm changeset (see Releasing below).

Development workflow

  • Build a single package: pnpm --filter @galalem/<package-name> build
  • Test in watch mode: pnpm --filter @galalem/<package-name> exec vitest
  • Consume locally from another repo (verifies the real published tarball):
    cd @galalem/<package-name> && pnpm pack   # → @galalem-<package-name>-x.y.z.tgz
    cd ~/other-project && pnpm add /abs/path/to/that.tgz
    Prefer pnpm pack over npm link — packing tests exactly what users download and avoids the "two copies of React" hazard that linking can cause.

Versioning & releasing

Releases are driven by Changesets and gated by a human-approved PR:

  1. Make your change in a package.
  2. Run pnpm changeset, pick the affected package(s) and a semver bump (patch / minor / major), and describe the change. This writes a small markdown file under .changeset/. Commit it with your change.
  3. On merge to main, the Release workflow opens (or updates) a "Version Packages" PR that applies the bumps and updates changelogs. Nothing publishes yet.
  4. Merging that PR triggers the workflow to publish only the changed packages to npm.

Semver, briefly: patch = bug fix, no API change · minor = backward-compatible addition · major = breaking change. Pre-1.0 packages may break on minors; note it in the changeset.

Compatibility policy

  • The React versions a package supports are declared as a range in peerDependencies (e.g. ">=18"), never a single pinned version.
  • That range is a promise: CI runs each package's tests against every major React version in the range (via a test matrix). We only widen the range after CI is green on the new version.
  • Avoid React internals and undocumented APIs so packages survive framework majors untouched.

Contributing

  • One focused change per PR; include a changeset for any user-facing change.
  • Keep the public surface minimal — everything exported from src/index.ts is API you have to support.
  • Tests and types are part of the change, not a follow-up.

For automated contributors (AI agents)

This section is the assignment. If you are an agent working in this repo:

  • Your job is to build, maintain, and release small React packages under the @galalem scope that satisfy The package contract above. Read the Philosophy — those principles override convenience.
  • Adding a package: follow Creating a new package. Do not deviate from the required package.json shape (peer-dep React, dual exports, files: ["dist"], public access).
  • Never add react/react-dom to a package's dependencies. Peer + dev only.
  • Never publish manually or edit CHANGELOG.md by hand. Ship a changeset and let the Release pipeline publish. The root is private and must stay unpublishable.
  • Definition of done for any package change: pnpm --filter <pkg> build and pnpm --filter <pkg> test both pass, types are exported from src/index.ts, the package README.md reflects the change, and a changeset is included.
  • When unsure about scope, API surface, or a breaking change, prefer the smaller, more conservative option and surface the question rather than guessing.

License

MIT © Galalem

About

A monorepo of small, focused, open-source React libraries — independently versioned and published to npm under the [`@galalem`](https://www.npmjs.com/org/galalem) scope.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages