npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@croacroa/react-native-template

v3.7.0

Published

Production-ready React Native template with Expo, authentication, i18n, offline support, and more

Readme

@croacroa/react-native-template

npm version License: MIT TypeScript Expo SDK PRs Welcome

A production-ready React Native template with Expo SDK 52, featuring authentication, i18n, biometrics, offline support, and more.

✨ Features

Core

  • Expo SDK 52 with TypeScript
  • Expo Router for file-based navigation
  • NativeWind (Tailwind CSS) for styling
  • Zustand for state management
  • TanStack Query with offline persistence
  • React Hook Form + Zod for form validation

Authentication & Security

  • Auth Adapter Pattern - Easy switching between Supabase, Firebase, etc.
  • Biometric Auth - Face ID / Touch ID support
  • Secure token storage with expo-secure-store
  • Automatic token refresh with race condition handling

Internationalization

  • i18n with expo-localization + i18next
  • 5 locales included (English, French, Spanish, German, Arabic)
  • Language detection and persistence

UX Features

  • Dark/Light Theme with system preference support
  • Onboarding Screens with animated pagination
  • Push Notifications with Expo Notifications
  • Toast Notifications with Burnt
  • Deep Linking support with route parsing
  • Skeleton Loaders with shimmer animation
  • Offline Support with connection status toasts
  • OTA Updates with expo-updates integration

UI Components

  • Button, Input, Card, Modal, Skeleton
  • Select/Dropdown, Checkbox, Switch
  • BottomSheet with @gorhom/bottom-sheet
  • Avatar with initials fallback
  • Badge, Chip, CountBadge
  • OptimizedImage with expo-image
  • CountdownTimer with animated progress bar
  • SessionTimeoutModal with auto-signout
  • PermissionRationale pre-permission dialog
  • ForceUpdateScreen non-dismissible update gate

Animations & Transitions

  • Animation Presets (timing, spring, bounce)
  • Screen Transitions (slide, fade, modal) for Expo Router
  • useAnimatedEntry & useStaggeredEntry hooks
  • useParallax scroll effect hook
  • AnimatedScreen & AnimatedListItem components

Permissions

  • Centralized Permission Manager for all Expo permissions
  • usePermission hook with auto-refresh on app resume
  • PermissionGate component for declarative permission UI

Social Login

  • Google Sign-In via expo-auth-session with PKCE
  • Apple Sign-In via expo-apple-authentication (iOS)
  • SocialLoginButtons component with platform-aware display

Analytics

  • Analytics Adapter Pattern — pluggable providers (PostHog, Mixpanel, etc.)
  • Auto screen tracking via Expo Router
  • useTrackEvent hook for custom events

Payments & Subscriptions

  • Payment Adapter Pattern — pluggable providers (RevenueCat, Stripe, etc.)
  • Paywall component with product listing
  • useSubscription hook for subscription status

File Upload & Media

  • Image picker (camera + library) with compression
  • Upload with progress tracking, cancel, retry
  • ImagePickerButton & UploadProgress components

Real-time / WebSockets

  • WebSocketManager with auto-reconnect & exponential backoff
  • useChannel & usePresence hooks
  • Offline queue & auth token injection

Production Services

  • Logger Service — Structured logging with adapter pattern, PII scrubbing, scoped loggers via Logger.withContext()
  • Remote Config — Adapter pattern for Firebase/LaunchDarkly, useRemoteConfig hook
  • SQLite Database — Auto-migration system with Database facade and useDatabase hook
  • Session Management — Activity-based timeout with warning modal and auto-signout
  • Retry & Circuit Breaker — Exponential backoff, jitter, circuit breaker states, request deduplication
  • Request Interceptors — Correlation ID, user agent, request timing, request signing
  • PII Scrubbing — Automatic redaction of emails, phone numbers, credit cards, JWTs in logs and Sentry events
  • Debug Menu — Dev-only panel with env info, network requests, AsyncStorage viewer, feature flags

Party Game Infrastructure

  • SoundManager — Singleton audio manager with preload, play, stop, volume control via expo-av
  • useSound & useSoundEffects — React hooks for single and batched sound playback with auto-cleanup
  • useHaptics — Impact, notification, and selection haptic feedback via expo-haptics
  • useKeepAwake — Prevent screen sleep during game sessions via expo-keep-awake
  • useCountdown — Timer with start/pause/reset, progress tracking, and onFinish callback
  • CountdownTimer — Visual countdown component with animated progress bar (Reanimated)
  • useScreenOrientation — Lock/unlock screen orientation with auto-unlock on unmount
  • useShare — Cross-platform sharing (files via expo-sharing, text via RN Share)

DevOps & Quality

  • GitHub Actions CI/CD workflows
  • Maestro E2E tests
  • Sentry for crash reporting with PII scrubbing
  • Analytics Adapter for multiple providers
  • Performance Monitoring hooks
  • Accessibility — All 27 UI components have a11y attributes via centralized builders; utilities, hooks, and 26 a11y tests
  • Jest + Testing Library with 420+ tests across 35 suites
  • Storybook with 15 component stories
  • ESLint + Prettier + Husky for code quality

🚀 Quick Start

Option 1: Using npx (Recommended)

npx create-expo-app my-app --template @croacroa/react-native-template
cd my-app
npm install

Option 2: Using degit

npx degit croacroa-dev-team/template-react-native my-app
cd my-app
./scripts/init.sh  # macOS/Linux
# or
.\scripts\init.ps1  # Windows PowerShell

Option 3: Clone Repository

git clone https://github.com/croacroa-dev-team/template-react-native my-app
cd my-app
rm -rf .git
npm install
cp .env.example .env

Then update:

  • app.config.ts - App name, bundle ID, scheme
  • package.json - Package name
  • constants/config.ts - API URLs

Run the App

npm start           # Start development server
npm run ios         # Run on iOS simulator
npm run android     # Run on Android emulator

📁 Project Structure

├── app/                    # Expo Router pages
│   ├── (auth)/            # Protected routes (home, profile, settings)
│   ├── (public)/          # Public routes (login, register, forgot-password)
│   └── _layout.tsx        # Root layout with providers
├── components/
│   ├── ui/                # UI components (Button, Card, Modal, Skeleton, etc.)
│   ├── dev/               # Debug menu (dev-only)
│   ├── forms/             # Form components (FormInput)
│   ├── providers/         # AnalyticsProvider, SuspenseBoundary
│   └── ErrorBoundary.tsx  # Global error handling
├── hooks/                 # useAuth, useTheme, useSound, useCountdown, useHaptics, ...
├── stores/                # Zustand stores (appStore, notificationStore)
├── services/
│   ├── api.ts            # HTTP client with 401 retry & ETag caching
│   ├── logger/           # Structured logging with adapter pattern
│   ├── database/         # SQLite with auto-migration system
│   ├── session/          # Session timeout management
│   ├── config/           # Remote config adapter
│   ├── feature-flags/    # Feature flags & A/B testing
│   ├── payments/         # Payment adapter (RevenueCat, Stripe, etc.)
│   ├── analytics/        # Analytics adapter (PostHog, Mixpanel, etc.)
│   ├── realtime/         # WebSocket manager with reconnect
│   ├── auth/             # Social login (Google, Apple)
│   ├── media/            # Image picker, compression, upload
│   ├── permissions/      # Centralized permission manager
│   ├── sound/            # SoundManager singleton (expo-av)
│   ├── sentry.ts         # Crash reporting with PII scrubbing
│   ├── queryClient.ts    # TanStack Query with persistence
│   └── storage.ts        # AsyncStorage & SecureStore helpers
├── utils/                 # cn, toast, validation, piiScrubber
├── constants/             # App configuration
├── types/                 # TypeScript types
├── __tests__/             # Test files (420+ tests, 35 suites)
├── docs/guides/           # Integration guides (Supabase, RevenueCat, etc.)
└── scripts/               # Init scripts for template setup

🔐 Authentication

Complete auth flow with automatic token refresh:

import { useAuth } from "@/hooks/useAuth";

function MyComponent() {
  const {
    user,
    isAuthenticated,
    isLoading,
    signIn,
    signUp,
    signOut,
    updateUser,
    refreshSession,
  } = useAuth();
}

Features:

  • Tokens stored securely with expo-secure-store
  • Automatic refresh 5 minutes before expiry
  • Race condition handling for concurrent requests
  • Redirect to login on session expiry

📡 API Client

Robust HTTP client with automatic retry:

import { api } from "@/services/api";

// Basic requests
const users = await api.get<User[]>("/users");
const user = await api.post<User>("/users", { name: "John" });
await api.put("/users/1", { name: "Jane" });
await api.delete("/users/1");

// Skip auth for public endpoints
await api.get("/public", { requiresAuth: false });

401 Handling

The API client automatically:

  1. Catches 401 responses
  2. Refreshes the access token
  3. Retries the original request
  4. Redirects to login if refresh fails

📊 Data Fetching

TanStack Query with offline persistence:

import { useCurrentUser, useUpdateUser } from "@/hooks/useApi";

function Profile() {
  const { data: user, isLoading, error } = useCurrentUser();
  const updateUser = useUpdateUser();

  const handleUpdate = () => {
    updateUser.mutate(
      { name: "New Name" },
      { onSuccess: () => toast.success("Updated!") }
    );
  };
}

CRUD Factory

Create hooks for any resource:

import { createCrudHooks } from "@/hooks/useApi";

const postsApi = createCrudHooks<Post>({
  baseKey: ["posts"],
  endpoint: "/posts",
  entityName: "Post",
});

// Usage
const { data: posts } = postsApi.useList();
const { data: post } = postsApi.useById("123");
const createPost = postsApi.useCreate();

📴 Offline Support

Automatic offline handling:

import { useOffline } from "@/hooks/useOffline";

function MyComponent() {
  const { isOffline, isOnline } = useOffline({ showToast: true });
  // Shows toast when connection lost/restored
}

Query cache persisted to AsyncStorage - data available offline.

🎨 Skeleton Loaders

Pre-built skeleton components:

import {
  Skeleton,
  SkeletonText,
  SkeletonCard,
  SkeletonProfile,
  SkeletonList,
} from "@/components/ui/Skeleton";

// Single skeleton
<Skeleton width={200} height={20} />

// Profile placeholder
<SkeletonProfile />

// List of cards
<SkeletonList count={5} variant="card" />

🔔 Toast Notifications

Centralized toast system:

import { toast, handleApiError } from "@/utils/toast";

// Simple toasts
toast.success("Profile updated");
toast.error("Something went wrong", "Please try again");
toast.info("New message received");

// Handle API errors automatically
try {
  await api.post("/endpoint", data);
} catch (error) {
  handleApiError(error); // Shows appropriate toast
}

🛡️ Error Boundary

Global error handling with Sentry:

// Already wrapped in _layout.tsx
<ErrorBoundary>
  <App />
</ErrorBoundary>;

// Or use HOC for specific components
import { withErrorBoundary } from "@/components/ErrorBoundary";

const SafeComponent = withErrorBoundary(RiskyComponent);

📋 Form Validation

React Hook Form + Zod:

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { FormInput } from "@/components/forms";
import { loginSchema, LoginFormData } from "@/utils/validation";

function LoginForm() {
  const { control, handleSubmit } = useForm<LoginFormData>({
    resolver: zodResolver(loginSchema),
  });

  return (
    <FormInput
      name="email"
      control={control}
      label="Email"
      keyboardType="email-address"
    />
  );
}

Pre-built schemas: loginSchema, registerSchema, forgotPasswordSchema, profileSchema

🎭 Theming

Dark/light mode with persistence:

import { useTheme } from "@/hooks/useTheme";

function MyComponent() {
  const { isDark, mode, toggleTheme, setMode } = useTheme();
  // mode: 'light' | 'dark' | 'system'
}

🔧 Configuration

Environment Variables

# .env
EXPO_PUBLIC_SENTRY_DSN=your-sentry-dsn

Sentry Setup

  1. Create project at sentry.io
  2. Copy DSN to .env
  3. Errors automatically reported in production

🧪 Testing

420+ tests across 35 suites:

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # With coverage

Test coverage:

  • useAuth hook - 24 tests
  • ApiClient - 22 tests
  • useWebSocket - 12 tests
  • usePayments - 10 tests
  • usePermission - 8 tests
  • useMedia - 8 tests
  • useAnimations - 19 tests
  • useAnalytics - 10 tests
  • Accessibility - 26 tests
  • UI components & snapshots - 18 tests
  • Performance - 15 tests
  • CircuitBreaker, Retry, Deduplicator - 24 tests
  • Interceptors, SessionManager - 22 tests
  • Security, Storage, ForceUpdate - 33 tests
  • Logger, Validation, VersionGate - 39 tests
  • Accessibility builders - 28 tests

📜 Available Scripts

| Command | Description | | ----------------------- | ------------------------- | | npm start | Start Expo dev server | | npm run ios | Run on iOS simulator | | npm run android | Run on Android emulator | | npm test | Run tests | | npm run storybook | Start Storybook | | npm run lint | Run ESLint | | npm run typecheck | TypeScript check | | npm run ci | Lint + typecheck + test | | npm run format:check | Check Prettier formatting | | npm run build:dev | Build development client | | npm run build:preview | Build preview APK/IPA | | npm run build:prod | Build production release |

✅ Customization Checklist

  • [ ] Run init script or manually update placeholders
  • [ ] Replace icons in assets/images/
  • [ ] Configure API URL in constants/config.ts
  • [ ] Set up Sentry DSN in .env
  • [ ] Configure EAS: eas build:configure
  • [ ] Implement real API calls in services/api.ts
  • [ ] Add your analytics

📄 License

MIT