# Contributing

> How to file issues, propose changes, and add components to the OTF SDK.

The OTF SDK is **MIT-licensed and open**. The kits are commercial. This page is about
contributing to the SDK side.

## Where to file things

| Kind                              | Where                                                                        |
| --------------------------------- | ---------------------------------------------------------------------------- |
| Bug in `@otfdashkit/{ui, ui-native, tokens}` | [github.com/otf-kit/sdk/issues](https://github.com/otf-kit/sdk/issues) |
| Component request                 | Open a Discussion on the SDK repo with the use case + a sketch of the API   |
| Docs typo / clarification         | PR the relevant `.mdx` in `apps/docs/content/`                                |
| Question                          | [GitHub Discussions](https://github.com/otf-kit/sdk/discussions) — we read everything |
| Bug in a paid kit                 | Email support after purchase; private kit repos have an issue tracker         |

## Local setup

```bash
git clone git@github.com:otf-kit/sdk.git
cd sdk
pnpm install
```

Then pick what you're working on:

| Goal                              | Command                                                |
| --------------------------------- | ------------------------------------------------------ |
| Storybook (web components)        | `pnpm --filter @otfdashkit/storybook-web dev`           |
| Storybook (native components)     | `pnpm --filter @otfdashkit/storybook-native dev`        |
| Native showcase app               | `pnpm --filter @otfdashkit/ui-native-showcase dev`     |
| Docs site                         | `pnpm --filter @otfdashkit/docs dev`                    |
| Build a single package            | `pnpm --filter @otfdashkit/<pkg> build`                 |
| Type-check the whole repo         | `pnpm type-check`                                       |
| Lint the whole repo               | `pnpm lint`                                             |

## Commit conventions

We use [Conventional Commits](https://www.conventionalcommits.org/):

- `feat(ui): add Marquee primitive` — new feature
- `fix(ui-native): center `BottomSheet` snap points` — bug fix
- `docs: clarify token CSS load order` — docs only
- `chore(deps): bump fumadocs-ui` — chores
- `refactor(ui): split data-grid into rendering + state` — internal change

Scope is the package name without the org prefix (`ui`, `ui-native`, `tokens`, `docs`,
`storybook-web`, `storybook-native`).

## Adding a component

1. **Open a Discussion first.** Don't surprise us with a 1000-line PR for a component we
   wouldn't merge. We're stricter about what ships than most libraries because the SDK feeds
   the paid kits — every new component is a long-term maintenance commitment.

2. **Write Storybook stories before the component is final.** Real usage flushes out API
   issues that look fine in isolation.

3. **Follow the file convention.** `kebab-case.tsx` filename, `PascalCase` exported
   identifiers, single file per component (no `index.ts` re-exports inside the component
   folder).

4. **Read tokens, don't redefine them.** No hardcoded hex. No inline `style={{ background: ... }}`.
   `@otfdashkit/eslint-plugin-otf-design` will flag both.

5. **Test against the four shipped themes.** A component that looks great in `theme-slate`
   dark and breaks in `theme-warm` light isn't done.

6. **Document on the same PR.** Update the relevant `apps/docs/content/docs/components/.../*.mdx`
   in the same PR. We don't merge undocumented components.

## Testing

There's no full E2E suite yet — the SDK is small enough that visual review via Storybook
and the showcase apps is sufficient. We're considering Playwright + visual regression once
the storybook coverage is broader.

If you do add tests, place them next to the component (`MyComponent.test.tsx`) and prefer
testing-library / RNTL over snapshots.

## Code style

- **No comments unless explaining a non-obvious *why*.** The component name + types should
  carry the *what*. If you need a comment, lead with `// Why: ...`.

- **Strict TypeScript.** No `any`, no `as` casts unless documented. `forwardRef` only on
  DOM-leaf components.

- **Functional components only.** Hooks for state. No class components.

- **`data-slot` attribute on every custom component** — it's how design-system tooling pin-points
  parts.

- **Tailwind utility classes only on web.** No `style={{}}` for layout. Tokens for color.

## Lessons-first

If you hit a non-trivial bug while developing, **grep `docs/lessons.md` first.** Several
commonly-seen failure modes (Metro `Unable to resolve "@otfdashkit/ui-native"`, dual-React
crashes, tamagui peer-dep gotchas) have documented fixes. Use them, don't rebuild them.
After fixing a non-trivial issue yourself, append a new lesson.

## Release process

The SDK ships as scoped npm packages under the `otfdashkit` org:

- [`@otfdashkit/ui`](https://www.npmjs.com/package/@otfdashkit/ui)
- [`@otfdashkit/ui-native`](https://www.npmjs.com/package/@otfdashkit/ui-native)
- [`@otfdashkit/tokens`](https://www.npmjs.com/package/@otfdashkit/tokens)
- [`@otfdashkit/eslint-plugin-otf-design`](https://www.npmjs.com/package/@otfdashkit/eslint-plugin-otf-design)

We release together — one version, all packages. Currently at `v0.1.0` (alpha). Breaking
changes possible at minor versions until `v1.0.0`. Pin a specific version if that matters
to you.

## License

SDK packages are **MIT**. The kits are **commercial** under a separate license (see each
kit's `LICENSE-KIT.md`). You can use the SDK in any project — commercial or non-commercial —
without paying for a kit.
