A modern, production-ready starter for building React Native TypeScript libraries. Ships with dual CJS/ESM output, full test coverage, and AI-ready project conventions out of the box.
- Interactive setup wizard β run
npm run setupafter cloning to configure your library name, author, repo URLs, license, and keywords step by step. Validates every field, shows a preview, and writes all files in one go. - Husky v9 β hooks migrated to the v9 format. Git hooks now install automatically on
npm installwith no extra step.
See the full CHANGELOG for all changes including the 2.0.0 redesign.
- 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 v9 + commitlint β conventional commit enforcement, hooks install on
npm install - GitHub Actions β CI pipeline (typecheck + lint + test + build)
- AI-Ready β
AGENTS.md, Cursor rules, and full TSDoc on every export - Interactive setup wizard β
npm run setupto configure your library in 60 seconds - 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 installGit hooks are installed automatically when you run npm install (via the prepare script). No extra step needed.
Run 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
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)
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