Thanks for contributing. This guide covers how to send a change and how releases work.
- Setup, scripts, and the project layout are in DEVELOPMENT.md.
- Code, styling, docs, test, and writing rules are in AGENTS.md. They apply to people and AI agents.
Pull requests are welcome. For a large change, open an issue first to discuss it with the maintainers.
Keep pull requests small, with one feature or fix in each. Two small PRs are easier to review than one big one.
-
Fork the repository.
-
Clone your fork and add the upstream remote:
git clone https://github.com/<your-username>/apsara.git cd apsara git remote add upstream https://github.com/raystack/apsara.git
-
Sync your local
mainwith upstream:git checkout main git pull upstream main
-
Install the dependencies with pnpm (npm and yarn are not supported):
pnpm install
-
Create a branch named
<type>/<name>, using the types from the commit convention:git checkout -b feat/flex-inline
-
Make your changes, commit, and push to your fork:
git push -u origin HEAD
-
Open a pull request against
mainon the repository.
A maintainer reviews the PR, then merges it, asks for changes, or closes it with an explanation. PRs are squash-merged, so the PR title becomes the commit message on main.
Use the commit convention: <type>: [<component>] <summary>, for example feat: [flex] add inline prop for inline-flex. The title describes the whole change, not the last commit.
- Write a
## Summarywith up to 5 bullets. Each bullet says what changed and why. - Link the issue with
Closes #<issue>, so it closes when the PR merges. - Add screenshots or a short video for visual changes.
- Do not add a test plan, a checklist, a list of changed files, or empty sections. Add another section only when a reviewer needs it, for example a migration note for a breaking change.
## Summary
- Add `inline` prop to `Flex` that renders `display: inline-flex` (off by default).
- Fix documented `wrap` values to match the component (`noWrap`, `wrapReverse`).
Closes #617Apsara is a public repo. Anyone can read PR titles, descriptions, branch names, and commit messages, so they must make sense to someone outside your team.
- Do not include internal tracker IDs (such as
ABC-123), tracker links, or tracker-generated branch names. - Do not mention internal projects, customers, private URLs, or internal chat threads.
- Link GitHub issues only.
- Choose the branch name before the first push. A closed PR keeps its branch name, and preview deployment comments include it.
- Tests pass:
pnpm test:apsara. - Lint passes:
pnpm lint. CI does not run lint, so check it locally. - The change adds no type errors:
pnpm exec tsc --noEmitinpackages/react. CI does not run this either. - The library builds:
pnpm build:apsara. - New or changed behavior has tests.
- The docs page is up to date:
index.mdx,demo.ts, andprops.tsinapps/www/src/content/docs/components/<name>/. - The branch is up to date with
main.
Do not worry if you miss a step. CI and the maintainers will help.
- PR Title: checks that the title follows the commit convention. It runs again when you edit the title.
- Tests: runs the Vitest suite and builds the library on Node 22 and 24. To reproduce it, run
pnpm test:apsaraandpnpm build:apsara. - Canary Release: publishes a preview build to pkg.pr.new and comments the install command on the PR. See Canary releases.
- Vercel: deploys a preview of the docs site with your changes.
Commit subjects and PR titles use <type>: [<component>] <summary>:
feat:for new featuresfix:for bug fixesrefactor:for code refactoringtest:for adding testschore:for maintenance tasks
[<component>] names the component or resource the change is about. Docs changes use [docs], for example fix: [docs] correct flex wrap values. List two or three components as [select, combobox]. Leave it out for changes across most of the library.
Write the summary in lowercase and in the imperative mood, and keep the subject under 70 characters. Do not use ! (feat!:) or a parenthesized scope (feat(grid):). Describe breaking changes in the PR description.
git commit -m "feat: [button] add new variant"
git commit -m "fix: [tooltip] resolve positioning issue"
git commit -m "chore: [deps] support lucide 1.x"
git commit -m "feat: integrate react 19"Maintainers release by pushing a version tag. The tag must be on main or a release/* branch.
| Tag | Workflow | npm tag |
|---|---|---|
v1.2.3 |
release.yaml |
latest |
v1.2.3-rc.1 |
release-rc.yaml |
next |
git checkout main
git pull origin main
git tag v1.2.3
git push origin v1.2.3The workflow installs dependencies, builds the library, sets the package versions from the tag, publishes @raystack/apsara and @raystack/tools-config to npm, and creates a GitHub release with generated notes. It does not run the tests, so make sure main is green first.
Every push to a pull request or to main publishes a preview build to pkg.pr.new (canary.yaml). On a PR, pkg.pr.new comments with the install command:
pnpm add https://pkg.pr.new/raystack/apsara/@raystack/apsara@<pr-number>For a commit on main, use the commit SHA instead of the PR number.
- Migration guide: how to move from the Radix-based release to the Base UI-based version.
- RFCs: design proposals for major features.
Search the GitHub issues and the documentation site. If you do not find an answer, open an issue.
Be respectful, inclusive, and collaborative in all interactions.