How I Created a Versatile Mobile Toolkit App

Introduction
In a world where we constantly switch between dozens of single-purpose apps, I wanted to build something different—a single, beautifully designed mobile application that bundles everyday utility tools into one cohesive experience. That idea became Toolify, a React Native toolkit app packing 11 fully functional tools.
Toolify isn't just a collection of simple forms; it's a versatile powerhouse that integrates a sleek dark UI, a modular architecture, and complex native device capabilities—handling everything from hardware sensors like the compass to real-time network benchmarks—all within one runtime.
In this article, I walk through the entire journey—from the initial concept and technology choices to the architecture, design system, and the implementation details of each tool.
The Vision
The goal was simple: create a Swiss-army-knife mobile app that feels native, looks premium, and works offline. Instead of cluttering your home screen with a compass app, a calculator, a unit converter, a password generator, and a stopwatch, Toolify brings them all under one roof with a consistent, polished experience.
Technology Stack
Choosing the right technology was critical for balancing development speed with native performance. Here is what I went with and why:
| Technology | Purpose | Why? |
|---|---|---|
| React Native + Expo SDK 54 | Cross-platform development | Access to native APIs without writing native code; managed workflow and EAS updates. |
| TypeScript | Language | Type safety and vastly improved developer experience/maintainability. |
| React Navigation 7 | Navigation | Native stack navigation between tools for a natural feel. |
| Zustand | State Management | Lightweight, powerful, and simpler than Redux; native support for persistence. |
| Lucide React Native | Iconography | Beautiful, consistent, and customizable icon set. |
| expo-sensors | Hardware Access | Unified API for the Magnetometer (Compass) and Accelerometer (Bubble Level). |
| react-native-svg | Data Visualization | Resolution-independent rendering for custom gauges, compass dials, and QR codes. |
| AsyncStorage | Local Storage | Persistent storage for user data (like tasks), integrated via Zustand middleware. |
Other essential Expo libraries (expo-camera, expo-clipboard, expo-image-picker) were used to unlock specific device features as needed.
Architecture and Project Structure
A key principle was modularity. To ensure the app could scale to 11 tools (and beyond) without becoming a maintenance nightmare, each tool lives in its own self-contained module directory.
src/
├── components/ # Shared UI components (e.g., ToolCard, CustomButton)
├── constants/
│ └── theme.ts # Centralized design tokens (colors, spacing, typography)
├── modules/ # Feature modules - one self-contained directory per tool
│ ├── bmiCalculator/
│ ├── calculator/
│ ├── compass/
│ │ ├── CompassScreen.tsx
│ │ └── CompassDial.tsx # SVG component
│ ├── taskManager/
│ │ ├── store.ts # Zustand store with persistence
│ │ └── TaskManagerScreen.tsx
│ └── ... (other tools)
├── navigation/
│ └── RootNavigator.tsx # Central navigation configuration
└── screens/
└── HomeScreen.tsx # The tool grid dashboard
Why This Structure Works
Separation of Concerns: Each module owns its UI, logic, and (where needed) its own state store. There is zero coupling between tools.
Scalability: Adding a new tool is trivial. I create a folder under
src/modules/, register a new route inRootNavigator.tsx, and add a card to theHomeScreen.tsx. Zero refactoring required.Discoverability: The folder structure is self-documenting. You can see every feature of the app at a glance.
The Design System
Consistency was non-negotiable. Every screen, card, and button draws from a single source of truth in src/constants/theme.ts:
export const Theme = {
colors: {
background: '#121212', // Deep charcoal
surface: '#1E1E1E', // Card background
surfaceLight: '#2C2C2C', // Inputs and hover states
primary: '#00E5FF', // Electric Blue accent
text: '#FFFFFF',
textSecondary: '#A0A0A0',
border: '#333333',
success: '#03DAC6',
},
spacing: { xs: 4, s: 8, m: 16, l: 24, xl: 32 },
radii: { m: 8, l: 12, xl: 20, round: 9999 },
typography: {
h1: { fontSize: 32, fontWeight: 'bold' },
body: { fontSize: 16, fontWeight: 'normal' },
},
};
Screenshot of the Home Screen grid showing the design system in action
The dark theme with an electric blue accent (#00E5FF) gives the app a modern, tech-forward aesthetic. Every component references Theme directly—eliminating magic numbers, inconsistent padding, and color drift.
The navigation bar also inherits from this theme by extending React Navigation's DarkTheme:
// in RootNavigator.tsx
const AppTheme = {
...DarkTheme,
colors: {
...DarkTheme.colors,
primary: Theme.colors.primary,
background: Theme.colors.background,
card: Theme.colors.surface,
text: Theme.colors.text,
border: Theme.colors.border,
},
};
Deep Dive: Implementing the 11 Tools
The core challenge of Toolify was implementing 11 distinct feature sets while maintaining a unified architecture. Here is how some of the key tools were built.
1. Calculator (Basic and Scientific)
Side-by-side screenshots of Basic and Scientific Calculator modes
The calculator supports two modes toggled via a simple segment control: Basic arithmetic and Scientific functions (trig, logs, powers).
The expression is built as a string as the user taps buttons. To evaluate it, I created a prepareExpression() function that transforms human-readable notation into JavaScript-compatible math calls (e.g., sin( becomes Math.sin(, ^ becomes **). The final string is evaluated using a sandboxed new Function() call for safety.
2. Unit Converter
This tool supports Length, Weight, and Temperature with instant conversion as you type.
Length and Weight use a base-unit conversion strategy: everything converts to/from a base unit (meters or grams) using a central multiplier map. This avoids \(N^2\) conversion formulas. Temperature, however, requires explicit formulas (e.g., Celsius to Fahrenheit), which are handled separately.
3. Hardware Sensors: Compass and Bubble Level
Screenshot of the Compass (showing SVG dial) and Bubble Level (showing green 'level' state)
These tools utilize the device’s hardware sensors via expo-sensors.
Compass: Uses the Magnetometer. We calculate the heading via
atan2(y, x)from the raw data. To ensure a premium feel, we apply a low-pass filter (smoothing the data by blending 80% new reading with 20% previous) to reduce jitter, and handle the "wrap-around" logic to prevent sharp jumps when crossing the 359°\(\rightarrow\)0° boundary. The dial is a custom SVG that rotates smoothly.Bubble Level: Uses the Accelerometer to measure tilt on the X and Y axes. The UI renders a dynamic SVG "bubble" that moves within a circular gauge, changing color (Green/Orange/Red) based on the degree of tilt.
4. Task Manager (Persistent To-Do List)
This is a full CRUD (Create, Read, Update, Delete) task manager.
State is managed by Zustand using the persist middleware backed by AsyncStorage. This means the user's tasks are automatically saved locally and survive app restarts without requiring any manual "Save" logic. The store defines a clean, type-safe interface for all operations:
interface TaskState {
tasks: Task[];
addTask: (title: string) => void;
toggleTask: (id: string) => void;
editTask: (id: string, newTitle: string) => void;
deleteTask: (id: string) => void;
}
5. Internet Speed Test (Real Network Benchmarks)
screenshot of the Speed Test gauge animating during a download test
This is a genuine, active speed test that measures three distinct metrics against Cloudflare's speed test endpoints:
Ping: Measures the median latency of 5 rapid requests.
Download: Tracks real-time Mbps while downloading a 10MB file.
Upload: Measures throughput while POSTing 2MB of data.
The UI features a semicircular SVG gauge that animates during the test. To provide real-time updates, the download test uses a ReadableStream reader, calculating speed as chunks arrive rather than waiting for the entire 10MB file to complete.
Other Tools
QR Tools: Dual-mode tool using
expo-camerafor scanning andreact-native-qrcode-svg(styled with our primary theme color) for generation.Password Generator: Generates cryptographically random passwords with configurable length and character sets.
Stopwatch & Timer: Handles complex timing logic (laps, split times) with proper interval management. We use
useReffor the timer interval ID to ensure it persists across renders without triggering unnecessary re-updates.BMI Calculator: Straightforward health tool with color-coded results.
Text Scanner: A manual transcription assistant. Users capture an image of text (via camera or gallery) and can transcribe it into an editable field, providing a convenient reference layout.
Performance Considerations and Edge Cases
A utility app must be robust. We prioritized performance and handling edge cases throughout development:
Sensor Lifecycles: Sensor subscriptions (60ms interval for Compass, 80ms for Level) are aggressively cleaned up
useEffectreturn functions to prevent memory leaks and battery drain.Hardware Fallbacks: Both the Compass and Bubble Level check for sensor availability on mount, displaying friendly error messages on simulators or devices lacking the required hardware.
Error Handling: The Speed Test includes 30-second timeouts via
AbortControllerand catches network failures gracefully. The Calculator handlesNaN,Infinity, and expression errors without crashing.UX Details:
KeyboardAvoidingViewis used consistently (e.g., BMI Calculator, Task Manager) to ensure inputs are never obscured on iOS.
Building and Deployment
Toolify is configured for EAS Build with a streamlined configuration:
Android Package:
com.toolify.appFull edge-to-edge display support.
Orientation locked to Portrait.
Adaptive icons for Android and tablet support for iOS.
New Architecture enabled for React Native 0.81.5.
Lessons Learned and Next Steps
Start with the Design System: Defining colors, spacing, and typography upfront saved enormous time and ensured visual consistency across 11 distinct screens.
Modular Architecture Pays Off: Working on one tool without touching any other file made development fast and conflict-free.
Hardware Sensors Require Real Devices: Many sensor features cannot be fully tested on simulators. Building graceful fallbacks from day one was essential.
Toolify is designed to grow. Some ideas for the future include a camera-based Color Picker, a Sound Meter using the microphone, and a Ruler/Measurement tool utilizing AR.
Conclusion
Building Toolify proved that a well-architected React Native app can deliver a premium, native-feeling experience across a wide range of device capabilities—from hardware sensors and cameras to complex network benchmarks and persistent storage. By investing in a solid design system and a modular architecture early on, adding new tools became a predictable, low-risk, and enjoyable process.
Toolify is built with React Native 0.81.5, Expo SDK 54, and TypeScript 5.9.


