Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Bug report
about: Report something that isn't working
title: "[Bug] "
labels: bug
---

## Describe the bug

A clear and concise description of what the bug is.

## Reproduction

Steps to reproduce the behavior (a minimal repo or snippet is ideal):

1.
2.
3.

## Expected behavior

What you expected to happen.

## Environment

- Boilerplate commit / version:
- React Native version:
- React version:
- Node version:
- Platform: iOS / Android (and simulator vs. device)
- Xcode / Android SDK version:

## Additional context

Logs, screenshots, or anything else that helps. If this involves the AI service
layer, note the provider and whether streaming was enabled.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
blank_issues_enabled: true
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Feature request
about: Suggest an idea or improvement
title: "[Feature] "
labels: enhancement
---

## Problem

What problem are you trying to solve? What's missing or hard today?

## Proposed solution

What you'd like to see. If it touches the AI service layer, navigation, or
theming, describe how it fits the existing architecture.

## Alternatives considered

Any alternative approaches you've thought about.

## Additional context

Links, references, or examples from other projects.
24 changes: 24 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Summary

<!-- What does this PR change and why? -->

## Type of change

- [ ] Bug fix (non-breaking)
- [ ] New feature (non-breaking)
- [ ] Breaking change
- [ ] Docs / tooling / chore

## Checklist

- [ ] `npm run typecheck` passes
- [ ] `npm run lint` passes
- [ ] `npm run format:check` passes
- [ ] `npm test` passes
- [ ] I updated `CHANGELOG.md` under `## [Unreleased]`
- [ ] I did not rename public path aliases, hook return shapes, or AI service
exports (or I documented the break above)

## Related issues

<!-- e.g. Closes #123 -->
45 changes: 45 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

# Cancel superseded runs on the same ref.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
name: Lint · Typecheck · Test (Node ${{ matrix.node }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [22.x, 24.x]
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node ${{ matrix.node }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm

- name: Install dependencies
run: npm ci --legacy-peer-deps

- name: Typecheck
run: npm run typecheck

- name: Lint
run: npm run lint

- name: Prettier (check)
run: npm run format:check

- name: Test
run: npm test -- --runInBand --ci
4 changes: 2 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
node src/scripts/terminal/prettier.mjs
node src/scripts/terminal/lint.mjs
npm run typecheck
npm run lint
5 changes: 0 additions & 5 deletions .prettierrc.js

This file was deleted.

5 changes: 4 additions & 1 deletion App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { isAndroid } from "@freakycoder/react-native-helpers";
*/
import Navigation from "./src/navigation";

LogBox.ignoreAllLogs();
// Scope log suppression to known-benign third-party warnings only. Avoid
// LogBox.ignoreAllLogs() — it hides real bugs during development. Add specific
// message prefixes here as you encounter noisy, non-actionable warnings.
LogBox.ignoreLogs([]);

const App = () => {
const scheme = useColorScheme();
Expand Down
72 changes: 72 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Changelog

All notable changes to this project are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- **AI streaming now works on-device.** All three providers (`openai`,
`anthropic`, `gemini`) used `response.body.getReader()`, which is `undefined`
in React Native's `fetch` — `streamMessage` threw `"No response body"` and no
tokens ever arrived. Streaming now goes through an `XMLHttpRequest`-based SSE
transport (`src/services/ai/sse.ts`) that React Native supports.
- **SSE tokens split across network chunks are no longer dropped.** A new
`SSEParser` buffers partial lines across reads, so a `data:` line that arrives
in two pieces is reassembled instead of silently lost.
- **`@event-emitter` no longer imports the missing `events` module.** It was
importing Node's `events`, which Metro does not polyfill (and the package was
not installed), so the documented singleton failed to import. Replaced with a
small, dependency-free `EventEmitter` with the same public API.
- **`AIConfig.systemPrompt` is now honored.** It was documented but ignored;
`sendAIMessage` / `streamAIMessage` now prepend it as a system message when no
system message is already present.
- **TypeScript path aliases resolve.** `@models` and `@event-emitter` were used
in code/docs but missing from `tsconfig.json`; `@api` and `@local-storage`
pointed at non-existent folders. Added the missing `tsconfig` paths and real
stub folders, and fixed the `tsconfig`/RN base `moduleResolution` conflict so
`tsc --noEmit` runs clean.
- Static asset (`*.png`) type declarations moved to `assets.d.ts` so they remain
global pattern-ambient modules and `@assets/logo.png` type-resolves.

### Added

- **Test suite** (`__tests__/`): unit tests for the SSE parser, all three
providers (request shaping, response parsing, error mapping, streaming), the
service layer + system-prompt injection, the `useAIChat` / `useAICompletion`
hooks, and the event emitter — plus the existing App smoke test now runs under
a proper jest setup.
- **Continuous Integration** (`.github/workflows/ci.yml`): typecheck, lint,
Prettier check, and tests on a Node 22/24 matrix for every push and PR.
- `typecheck`, `lint:fix`, and `format:check` npm scripts; a `LICENSE` file
(MIT); `CONTRIBUTING.md`; a `CHANGELOG.md`; and GitHub issue/PR templates.
- Typed response shapes for the OpenAI / Anthropic / Gemini wire formats, and
`toAIError` / `extractApiErrorMessage` helpers exported from `@services/ai`.
- Gemini's `streamMessage` / `sendMessage` now respect `config.baseURL`,
matching the documented proxy/local-LLM override behavior of the other
providers.

### Changed

- **ESLint dependencies made explicit.** `@typescript-eslint/parser`,
`@typescript-eslint/eslint-plugin`, and `eslint-plugin-jest` were required by
the config but only present transitively; they are now direct devDependencies.
- `package.json` metadata: added `description`, `license`, `author`,
`repository`, `bugs`, `homepage`, and `keywords`.
- `npm run lint` / `npm run prettier` now invoke ESLint / Prettier directly
instead of the chalk/ora wrapper scripts (which depended on undeclared deps).
- Husky `pre-commit` runs `typecheck` + `lint`.
- Scoped `LogBox.ignoreAllLogs()` down to an explicit (empty) ignore list so
real warnings surface during development.
- Removed `route: any` and `useEffect((): any => …)` smells in the navigator.

### Removed

- Dead dependencies: `event`, `metro-react-native-babel-preset`,
`eslint-plugin-flowtype`, `eslint-plugin-ft-flow`, and the redundant
`@trivago/prettier-plugin-sort-imports` (kept `@ianvs`).
- Duplicate `.prettierrc.js` (the JSON `.prettierrc` is the single source of
truth) and the chalk/ora-based `src/scripts/terminal/*.mjs` runners.
67 changes: 67 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Contributing

Thanks for your interest in improving this boilerplate! This repo is a
clone-and-go starter template, so contributions that keep it lean, correct, and
well-documented are especially valuable.

## Getting set up

```sh
git clone https://github.com/kuraydev/react-native-typescript-boilerplate.git
cd react-native-typescript-boilerplate
npm install
```

iOS only:

```sh
cd ios && pod install && cd ..
```

## Before you open a PR

Run the same gates CI runs — all four must pass:

```sh
npm run typecheck # tsc --noEmit
npm run lint # eslint .
npm run format:check # prettier --check
npm test # jest
```

`npm run lint:fix` and `npm run prettier` auto-fix lint/format issues.

A Husky `pre-commit` hook runs `typecheck` + `lint` automatically, and
`commit-msg` validates your commit message.

## Commit messages

Commits must follow [Conventional Commits](https://www.conventionalcommits.org/)
(enforced by `commitlint`). Allowed types: `feat`, `fix`, `chore`, `docs`,
`style`, `refactor`, `perf`, `test`, `ci`, `revert`.

```
feat: add Mistral provider to the AI service layer
fix: buffer SSE lines split across network chunks
docs: document the New Architecture requirement
```

## Guidelines

- **TypeScript:** keep `strict` happy. Prefer typed wire shapes over `as any`.
- **Path aliases:** prefer aliases (`@services/ai`, `@hooks`, `@theme`, …) over
deep relative imports. Add a new alias to **both** `babel.config.js` and
`tsconfig.json`, then restart Metro with `npm run start:fresh`.
- **AI providers:** implement `IAIProvider` and keep the `onToken` / `onComplete`
/ `onError` callback contract stable. Reuse `streamSSE` from
`@services/ai` for streaming so line-buffering stays correct.
- **Tests:** add/adjust tests under `__tests__/` for any behavior change. Mock
`fetch` for non-streaming paths and the provided `MockXHR` helper for streaming.
- **Public surface:** this template's de-facto API is its path aliases, hook
return shapes, and AI service exports. Avoid renaming them without a clear,
documented reason.

## Reporting bugs / requesting features

Use the issue templates under `.github/ISSUE_TEMPLATE`. For bugs, include your
RN/Node/Xcode versions and a minimal reproduction.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Kuray (kuraydev)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading