Skip to main content
Contributions to Off Grid are welcome! This guide covers the fork-branch-PR workflow, pre-commit quality gates, code style, and the automated CI review loop.

Contribution Workflow

1

Fork the repository

  1. Go to github.com/alichherawalla/off-grid-mobile
  2. Click Fork in the top right
  3. Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/off-grid-mobile.git
cd off-grid-mobile
2

Create a feature branch

Use a descriptive branch name that indicates the type of change:
git checkout -b feat/your-feature-name
Never commit directly to main. Always create a feature branch.
3

Install dependencies

npm install
cd android && ./gradlew clean && cd ..
cd ios && pod install && cd ..
4

Make your changes

  • Follow the existing code style and conventions
  • Use useTheme() and useThemedStyles() for all styling - never hardcode colors
  • Use TYPOGRAPHY and SPACING from src/constants/ for theme-independent tokens
  • Write tests for new functionality
  • Update documentation if needed
5

Test your changes

Ensure all tests pass before committing:
npm test                  # Run all tests
npm run lint              # Lint code
npx tsc --noEmit          # Type check
See the Testing Guide for more details.
6

Commit your changes

The pre-commit hook will automatically run quality gates:
git add .
git commit -m "feat: add new feature description"
If the pre-commit hook fails, fix the issue and recommit. Never skip with --no-verify.
7

Push and create a pull request

git push -u origin feat/your-feature-name
Then:
  1. Go to GitHub and create a pull request from your branch to main
  2. Fill out the PR template (see below)
  3. Wait for automated reviews (Gemini, Codecov, SonarCloud)
  4. Address review feedback

Pre-Commit Quality Gates (Husky)

Off Grid uses Husky to automatically run quality gates on every git commit. The checks are scoped to the file types you staged, so you only run relevant tests.

What Runs When

Staged file typeChecks that run automatically
.ts / .tsx / .js / .jsxESLint (staged only), tsc --noEmit, npm test
.swiftSwiftLint (staged only), npm run test:ios
.kt / .ktscompileDebugKotlin (type check), lintDebug, npm run test:android

Requirements

  • SwiftLint: Install via brew install swiftlint (skipped with a warning if not installed)
  • Android checks: Require the Gradle wrapper in android/

Hook Behavior

Example pre-commit output
 JS/TS lint (staged files)...
 ESLint passed

 TypeScript type check...
 No type errors

 JS/TS tests...
 PASS  src/services/__tests__/llm.test.ts
 PASS  src/stores/__tests__/chatStore.test.ts
 All tests passed
Before writing new code, ensure tests exist for your changes. If the hook fails, fix the issue and recommit - never skip with --no-verify.

Code Style and Conventions

TypeScript Style

  • Use TypeScript for all new code
  • Define interfaces for all complex types
  • Avoid any - use proper types or unknown
  • Use descriptive variable names

React Native Style

  • Never hardcode colors - use useTheme() and colors.*
  • Never hardcode spacing/typography - use SPACING and TYPOGRAPHY constants
  • Always use useThemedStyles - never inline styles or static StyleSheet.create
  • No pixel values - use design tokens
Good example
const { colors } = useTheme();
const styles = useThemedStyles(createStyles);

const createStyles = (colors: ThemeColors) => ({
  container: {
    backgroundColor: colors.background,
    padding: SPACING.md,
  },
  title: {
    ...TYPOGRAPHY.h2,
    color: colors.text,
  },
});
Bad example
const styles = StyleSheet.create({
  container: {
    backgroundColor: '#000000',  // ❌ Hardcoded color
    padding: 12,                 // ❌ Magic number
  },
  title: {
    fontSize: 16,                // ❌ Hardcoded typography
    color: 'white',              // ❌ Hardcoded color
  },
});
  • Use functional components with hooks (no class components)
  • Keep components small and focused (single responsibility)
  • Extract reusable logic into custom hooks
  • Use AnimatedPressable for interactive elements (includes haptics)
  • Use AnimatedEntry or AnimatedListItem for list items (staggered animations)
  • Use FlatList or FlashList for large lists (not .map() inside ScrollView)
  • Use React.memo() for expensive components
  • Use useMemo() and useCallback() to prevent unnecessary re-renders
  • Check with React DevTools Profiler if unsure
  • Both platforms required - no new native module without Android + iOS implementations
  • Register in Xcode - add new iOS modules to project.pbxproj build target
  • Cross-platform paths - resolve file paths correctly on both platforms (no hardcoded / vs \\)
  • Progress reporting - long-running tasks must report progress to UI

Service Layer Guidelines

  • Singleton pattern for all core services (prevent duplicate instances)
  • Background-safe operations for long-running tasks (independent of component lifecycle)
  • Memory checks before model operations (check RAM budget)
  • Comprehensive logging for debugging
  • Graceful error handling with user-friendly messages

Testing Guidelines

  • Write tests for all new functionality
  • Test stores with @testing-library/react-native
  • Test services with Jest mocks
  • Test components with snapshot tests or RTL queries
  • Ensure coverage doesn’t decrease (Codecov will block PRs)

Pull Request Template

When creating a PR, fill out the template at .github/pull_request_template.md:
## Summary

<!-- Briefly describe what this PR does and why -->

## Type of Change

- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Refactor (code change that neither fixes a bug nor adds a feature)
- [ ] Chore (build process, CI, dependency updates, etc.)

## Screenshots / Screen Recordings

<!-- Mandatory for any UI change. Remove sections that don't apply. -->

### Android

| Before | After |
|--------|-------|
|        |       |

### iOS

| Before | After |
|--------|-------|
|        |       |

## Checklist

### General

- [ ] My code follows the project's coding style and conventions
- [ ] I have performed a self-review of my code
- [ ] I have added/updated comments where the logic isn't self-evident
- [ ] My changes generate no new warnings or errors

### Testing

- [ ] I have tested on **Android** (physical device or emulator)
- [ ] I have tested on **iOS** (physical device or simulator)
- [ ] I have tested in **light mode** and **dark mode**
- [ ] Existing tests pass locally (`npm test`)
- [ ] I have added tests that prove my fix is effective or my feature works

### React Native Specific

- [ ] No new native module without corresponding platform implementation (Android + iOS)
- [ ] New native modules are added to the Xcode project build target (`project.pbxproj`)
- [ ] No hardcoded pixel values — uses `SPACING` / `TYPOGRAPHY` constants from the theme
- [ ] Styles use `useThemedStyles` pattern (not inline or static `StyleSheet.create`)
- [ ] Animations/gestures work smoothly on both platforms
- [ ] Large lists use `FlatList` / `FlashList` (not `.map()` inside `ScrollView`)
- [ ] No unnecessary re-renders introduced (check with React DevTools Profiler if unsure)

### Performance & Models

- [ ] Downloads / long-running tasks report progress to the UI
- [ ] File paths are resolved correctly on both platforms (no hardcoded `/` vs `\\`)
- [ ] Large files (models, assets) are not committed to the repository

### Security

- [ ] No secrets, API keys, or credentials are included in the code
- [ ] User input is validated/sanitized where applicable

## Related Issues

<!-- Link any related issues: Fixes #123, Relates to #456 -->

## Additional Notes

<!-- Any context, trade-offs, or follow-up work worth mentioning -->
Do NOT include “Generated with Claude Code” or any AI attribution in PR descriptions.

CI Review Loop

After pushing your PR, three automated reviewers will analyze your code. You must address all feedback before merging.

Automated Reviewers

What it checks: Code quality, style, logic issues, best practicesHow to address:
  1. Pull down comments:
    gh api repos/alichherawalla/off-grid-mobile/pulls/YOUR_PR_NUMBER/comments
    gh api repos/alichherawalla/off-grid-mobile/pulls/YOUR_PR_NUMBER/reviews
    
  2. Fix code or reply explaining why the suggestion doesn’t apply
  3. Push fixes
  4. Comment /gemini review on the PR to trigger a fresh review pass
Example review comment:
Consider using useMemo here to prevent unnecessary recalculations on every render.

Review Loop Workflow

1

Push code

git push -u origin feat/your-feature
Wait for all three reviewers to report (usually 2-5 minutes).
2

Pull down feedback

# Gemini comments
gh api repos/alichherawalla/off-grid-mobile/pulls/YOUR_PR_NUMBER/comments
gh api repos/alichherawalla/off-grid-mobile/pulls/YOUR_PR_NUMBER/reviews

# Check CI status
gh pr checks
3

Address all feedback

  • Gemini: Fix code or reply with explanations
  • Codecov: Add tests for uncovered lines
  • SonarCloud: Fix security hotspots, code smells, and duplications
4

Re-run local quality gates

npm run lint && npm test && npx tsc --noEmit
Ensure everything passes locally before pushing.
5

Push fixes

git add .
git commit -m "fix: address review feedback"
git push
6

Re-trigger Gemini (if needed)

Comment on the PR:
/gemini review
This triggers a fresh Gemini review pass.
7

Repeat until green

Continue the loop until all three reviewers pass with no blocking issues:
  • ✅ Gemini: No unresolved comments
  • ✅ Codecov: Coverage maintained or increased
  • ✅ SonarCloud: Quality gate passed, no security hotspots

Development Guidelines Summary

Styling

  • Use useTheme() and useThemedStyles() for all styling
  • Never hardcode colors, spacing, or typography
  • Use TYPOGRAPHY and SPACING constants

Services

  • Follow singleton pattern
  • Implement background-safe operations
  • Check memory before model operations
  • Add comprehensive logging

Components

  • Functional components with hooks
  • Small, focused components
  • Use AnimatedPressable for interactions
  • Use FlatList for large lists

Testing

  • Write tests for all new functionality
  • Ensure coverage doesn’t decrease
  • Test on both Android and iOS
  • Test light and dark modes

Getting Help

Next Steps

Building from Source

Set up your development environment

Testing Guide

Learn how to run tests locally

Project Structure

Understand the codebase organization

Build docs developers (and LLMs) love