Code Reusability
One of the core strengths of Nespo.dev is its exceptional code reusability across web, mobile, and backend applications. This section explains how we achieve true code sharing without compromising platform-specific optimizations.
The Problem
Traditional multi-platform development often results in:
- Duplicate code across web and mobile
- Type mismatches between frontend and backend
- Inconsistent business logic
- Difficult synchronization of updates
- Multiple teams maintaining similar functionality
The Solution
Nespo.dev solves these problems through:
1. Shared Type System
A single source of truth for all type definitions.
Benefits
- Compile-time safety: Errors caught before runtime
- Auto-completion: Full IDE support across all platforms
- Consistency: Same data structures everywhere
- Documentation: Types serve as living documentation
Implementation
// packages/types/src/user.ts
export interface User {
id: string;
email: string;
name: string;
role: 'admin' | 'user' | 'guest';
createdAt: Date;
updatedAt: Date;
}
export interface CreateUserDto {
email: string;
name: string;
password: string;
}
export interface UpdateUserDto {
name?: string;
email?: string;
}
Used across all platforms:
// Web App (apps/web)
import { User } from '@nespo/types';
function UserProfile({ user }: { user: User }) {
return <div>{user.name}</div>;
}
// Mobile App (apps/mobile)
import { User } from '@nespo/types';
function UserScreen({ user }: { user: User }) {
return <Text>{user.name}</Text>;
}
// API (apps/api)
import { User, CreateUserDto } from '@nespo/types';
@Controller('users')
export class UsersController {
@Post()
create(@Body() dto: CreateUserDto): Promise<User> {
return this.usersService.create(dto);
}
}
2. Auto-Generated API Client
Zero-maintenance, type-safe API communication.
How It Works
- Backend defines API using NestJS decorators
- OpenAPI spec generated automatically from code
- Client code generated using OpenAPI Generator
- Type-safe client available in packages
Example
// packages/api-client/src/index.ts
// This file is AUTO-GENERATED - do not edit manually
export class UsersApi {
async getUsers(): Promise<User[]> {
const response = await fetch('/api/users');
return response.json();
}
async getUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
async createUser(data: CreateUserDto): Promise<User> {
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(data),
});
return response.json();
}
}
Using the client:
// Web or Mobile
import { apiClient } from '@nespo/api-client';
// Full type safety and autocomplete
async function fetchUsers() {
const users = await apiClient.users.getUsers();
// users is typed as User[]
const user = await apiClient.users.getUser('123');
// user is typed as User
}
3. Shared Business Logic
Reusable utilities and business logic functions.
Validation Logic
// packages/utils/src/validation.ts
export function validateEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
export function validatePassword(password: string): {
valid: boolean;
errors: string[];
} {
const errors: string[] = [];
if (password.length < 8) {
errors.push('Password must be at least 8 characters');
}
if (!/[A-Z]/.test(password)) {
errors.push('Password must contain an uppercase letter');
}
if (!/[0-9]/.test(password)) {
errors.push('Password must contain a number');
}
return {
valid: errors.length === 0,
errors,
};
}
Used everywhere:
// Web form validation
import { validateEmail, validatePassword } from '@nespo/utils';
function SignUpForm() {
const handleSubmit = (data) => {
if (!validateEmail(data.email)) {
setError('Invalid email');
return;
}
const { valid, errors } = validatePassword(data.password);
if (!valid) {
setErrors(errors);
return;
}
// Submit form
};
}
// Backend validation
import { validateEmail } from '@nespo/utils';
@Injectable()
export class UsersService {
async create(dto: CreateUserDto) {
if (!validateEmail(dto.email)) {
throw new BadRequestException('Invalid email');
}
// Create user
}
}
Date/Time Utilities
// packages/utils/src/date.ts
export function formatDate(date: Date): string {
return new Intl.DateTimeFormat('en-US').format(date);
}
export function getRelativeTime(date: Date): string {
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffMins = Math.floor(diffMs / 60000);
if (diffMins < 1) return 'Just now';
if (diffMins < 60) return `${diffMins} minutes ago`;
const diffHours = Math.floor(diffMins / 60);
if (diffHours < 24) return `${diffHours} hours ago`;
const diffDays = Math.floor(diffHours / 24);
return `${diffDays} days ago`;
}
4. Shared Constants
Configuration and constant values.
// packages/utils/src/constants.ts
export const APP_CONFIG = {
APP_NAME: 'Nespo',
API_VERSION: 'v1',
MAX_FILE_SIZE: 5 * 1024 * 1024, // 5MB
SUPPORTED_IMAGE_TYPES: ['image/jpeg', 'image/png', 'image/webp'],
PAGINATION: {
DEFAULT_PAGE_SIZE: 20,
MAX_PAGE_SIZE: 100,
},
};
export const ROUTES = {
HOME: '/',
LOGIN: '/login',
SIGNUP: '/signup',
DASHBOARD: '/dashboard',
PROFILE: '/profile',
} as const;
export const API_ENDPOINTS = {
USERS: '/api/users',
AUTH: '/api/auth',
POSTS: '/api/posts',
} as const;
Code Reuse Statistics
In a typical Nespo.dev project:
- ~60-70% of code is shared between web and mobile
- ~40-50% of code is shared across all three platforms
- 100% type safety across the entire stack
- 0% manual API client maintenance
Benefits
Development Speed
- Write once, use everywhere
- No duplicate implementations
- Consistent behavior across platforms
- Faster feature development
Maintainability
- Single source of truth
- Update once, deploy everywhere
- Easier refactoring
- Clear dependencies
Quality
- Fewer bugs from inconsistencies
- Better test coverage
- Type safety catches errors early
- Enforced standards
Cost Savings
- Smaller codebase to maintain
- Single team can handle all platforms
- Reduced QA effort
- Lower technical debt
Best Practices
DO:
✅ Share types, interfaces, and constants ✅ Share business logic and validation ✅ Share API client libraries ✅ Share utility functions ✅ Share configuration
DON'T:
❌ Share UI components directly (use composition) ❌ Share platform-specific code ❌ Share styling (except design tokens) ❌ Over-abstract simple code
Package Organization
packages/
├── types/ # Shared TypeScript types
│ ├── src/
│ │ ├── user.ts
│ │ ├── post.ts
│ │ └── index.ts
│ └── package.json
│
├── api-client/ # Generated API client
│ ├── src/
│ │ └── generated/
│ └── package.json
│
└── utils/ # Shared utilities
├── src/
│ ├── validation.ts
│ ├── date.ts
│ └── constants.ts
└── package.json
Next Steps
Learn more about specific implementations:
- Backend Features - NestJS architecture
- Frontend Features - Next.js patterns
- Mobile Features - Expo setup
Or explore the build system:
- Build System - TurboRepo configuration