A modern, production-ready starter for building React Native TypeScript libraries. Ships with dual CJS/ESM output, full test coverage, automated releases, and AI-ready project conventions out of the box.
- react-native-builder-bob β dual CJS + ESM + TypeScript declarations
- Strict TypeScript β
noImplicitAny,strictNullChecks,noUnusedLocals - Jest + @testing-library/react-native β full test suite with coverage thresholds
- ESLint + Prettier β consistent code style, enforced on commit via
lint-staged - Husky + commitlint β conventional commit enforcement
- semantic-release β automated versioning, changelog, and npm publish
- GitHub Actions β CI pipeline (typecheck + lint + test + build) and release pipeline
- AI-Ready β
AGENTS.md, Cursor rules, and full TSDoc on every export - Example component and hook β reference implementations to clone from
git clone https://github.com/WrathChaos/react-native-typescript-library-starter.git my-library
cd my-library
npm installnpm run husky:setupRun the interactive setup wizard. It walks through every field one by one, shows a preview of all planned changes, and asks for confirmation before writing anything:
npm run setupThe wizard will ask for:
- Package name β your npm name (e.g.
react-native-my-library) - Description β one sentence
- GitHub username / org β used to build repo URLs automatically
- GitHub repository name β defaults to your package name
- Author name & email
- License β MIT, Apache-2.0, ISC, GPL-3.0, or Unlicensed
- Keywords β optional, comma-separated extras
After confirmation it updates package.json, README.md, AGENTS.md, and CONTRIBUTING.md in one go.
The src/ folder contains a fully-typed example component and hook. Use them as reference, then replace with your own:
src/
βββ components/MyComponent/ β replace with your component
βββ hooks/useMyHook.ts β replace with your hook
βββ index.ts β update exports
npm run build # outputs to lib/
npm run typecheck # type-check without emitting
npm test # run the test suitereact-native-typescript-library-starter/
βββ src/ # ALL source code
β βββ index.ts # Public API entry point
β βββ components/
β β βββ MyComponent/
β β βββ MyComponent.tsx
β β βββ MyComponent.types.ts
β β βββ index.ts
β βββ hooks/
β β βββ useMyHook.ts
β βββ types/
β β βββ index.ts
β βββ __tests__/
β βββ MyComponent.test.tsx
β βββ useMyHook.test.ts
βββ lib/ # Generated by bob (git-ignored)
βββ .github/workflows/
β βββ ci.yml # PR checks
β βββ release.yml # Publish pipeline
βββ AGENTS.md # AI agent instructions
βββ CONTRIBUTING.md
βββ CHANGELOG.md
βββ package.json
βββ tsconfig.json
βββ tsconfig.build.json
βββ babel.config.js
| Command | Description |
|---|---|
npm run build |
Build library to lib/ via bob |
npm run typecheck |
Type-check without emitting |
npm run lint |
Run ESLint with colored output and auto-fix |
npm run lint:ci |
ESLint without spinner (for CI) |
npm run prettier |
Format source files |
npm run prettier:ci |
Check formatting (for CI) |
npm test |
Run Jest tests |
npm run test:watch |
Jest in watch mode |
npm run test:coverage |
Jest with coverage report |
react-native-builder-bob produces three output targets inside lib/:
| Output | Path | Used by |
|---|---|---|
| CommonJS | lib/commonjs/ |
Node.js, bundlers with require() |
| ESM | lib/module/ |
Modern bundlers, tree-shaking |
| TypeScript | lib/typescript/ |
Type declarations for consumers |
The package.json exports field routes consumers to the correct output automatically.
import { MyComponent } from "your-library";
export default function App() {
return (
<MyComponent
title="Hello World"
description="A fully-typed example component."
enableButton
buttonText="Tap me"
onPress={() => console.log("pressed")}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
β | Primary title text (required) |
description |
string |
β | Optional description below title |
enableButton |
boolean |
false |
Renders an action button |
buttonText |
string |
"Press me" |
Button label |
onPress |
() => void |
β | Button press callback |
style |
StyleProp<ViewStyle> |
β | Root container style override |
titleStyle |
StyleProp<TextStyle> |
β | Title text style override |
descriptionStyle |
StyleProp<TextStyle> |
β | Description text style override |
buttonStyle |
StyleProp<ViewStyle> |
β | Button container style override |
buttonTextStyle |
StyleProp<TextStyle> |
β | Button label style override |
accessibilityLabel |
string |
title |
Accessibility label for the container |
testID |
string |
"my-component" |
Test ID for querying in tests |
import { useMyHook } from "your-library";
function Counter() {
const { count, increment, decrement, reset, isAtMax, isAtMin } = useMyHook({
initialValue: 0,
max: 10,
min: 0,
step: 1,
});
return (
<View>
<Text>{count}</Text>
<Button title="+" onPress={increment} disabled={isAtMax} />
<Button title="-" onPress={decrement} disabled={isAtMin} />
<Button title="Reset" onPress={reset} />
</View>
);
}| Option | Type | Default | Description |
|---|---|---|---|
initialValue |
number |
0 |
Starting counter value |
max |
number |
β | Upper bound (no limit if omitted) |
min |
number |
0 |
Lower bound |
step |
number |
1 |
Increment/decrement amount |
| Key | Type | Description |
|---|---|---|
count |
number |
Current counter value |
increment |
() => void |
Increment by step |
decrement |
() => void |
Decrement by step |
reset |
() => void |
Reset to initialValue |
isAtMax |
boolean |
true when count >= max |
isAtMin |
boolean |
true when count <= min |
Tests use Jest and @testing-library/react-native.
npm test # run all tests
npm run test:coverage # with coverage reportCoverage thresholds are enforced in package.json:
- Branches: 70%
- Functions / Lines / Statements: 80%
This project enforces Conventional Commits via commitlint:
feat: add MyButton component
fix: correct accessibility role
test: add boundary cases for useMyHook
docs: update README with new props
chore: upgrade dependencies
Commits trigger automatic versioning via semantic-release:
fixβ patch releasefeatβ minor releasefeatwithBREAKING CHANGEfooter β major release
Runs on every push and pull request to main:
- Typecheck β
tsc --noEmit - Lint β ESLint + Prettier check
- Test β Jest with coverage
- Build β
bob build(only runs after all checks pass)
Runs on push to main after CI passes:
- Run full test suite
- Build library
semantic-releaseβ bump version, updateCHANGELOG.md, publish to npm, create GitHub release
Required secrets: NPM_TOKEN (in your GitHub repo settings).
This starter is designed to be AI-friendly:
AGENTS.mdβ read this file first when working with an AI agent. It contains the full directory map, all runnable commands, conventions, naming rules, and do/don'ts..cursor/rules/library-conventions.mdcβ Cursor AI rules that automatically enforce component/hook patterns.- TSDoc everywhere β every exported function, component, prop, and type has
@param,@returns, and@exampledocumentation. This maximises AI autocomplete quality. - Strict TypeScript β strict mode produces accurate types that AI tools can reason about reliably.
- Conventional Commits β predictable commit history helps AI tools summarize changes and generate release notes.
The .cursor/rules/library-conventions.mdc rule is auto-applied to all src/**/*.ts and src/**/*.tsx files. It enforces component structure, hook patterns, and TSDoc requirements.
Paste the contents of AGENTS.md into the system prompt or the start of a conversation for best results.
"peerDependencies": {
"react": ">=17.0.0",
"react-native": ">=0.70.0"
}See CONTRIBUTING.md for the full guide.
See CHANGELOG.md.
MIT β see LICENSE.
FreakyCoder β kurayogun@gmail.com
freakycoder.com