A modern monorepo demonstrating cross-platform type sharing between Web (Next.js), Mobile (React Native/Expo), and Backend (NestJS/GraphQL) applications.
- ๐ Cross-Platform Type Safety: Shared TypeScript types across all platforms
- ๐ฑ Multi-Platform Support: Web, iOS, Android, and Backend in one repo
- ๐ ๏ธ Shared Utilities: Common validation and utility functions
- ๐ฏ Type-Safe APIs: GraphQL with automatically generated types
- ๐ฆ Monorepo Architecture: Organized workspace with shared packages
- ๐ Hot Reloading: Development mode across all platforms simultaneously
devplify/
โโโ apps/
โ โโโ frontend/ # Next.js web application
โ โโโ mobile/ # React Native mobile app (Expo)
โ โโโ backend/ # NestJS GraphQL API
โโโ packages/
โ โโโ shared-types/ # Shared TypeScript types
โ โโโ shared-utils/ # Shared utility functions
โโโ prisma/
โ โโโ schema.prisma # Database schema
โโโ package.json # Root package.json
โโโ turbo.json # Turborepo configuration
- Node.js 18+
- npm or yarn
- Git
-
Clone the repository
git clone <repository-url> cd devplify
-
Install dependencies
npm install
-
Build shared packages
cd packages/shared-types && npm run build cd ../shared-utils && npm run build
-
Start all development servers
# Starts backend, frontend, and mobile simultaneously npm run dev # Or start individual platforms npm run dev:backend # NestJS API on port 3001 npm run dev:web # Next.js on port 3000 npm run dev:mobile # Expo development server
- Location:
apps/frontend/
- URL: http://localhost:3000
- Tech Stack: Next.js, NextAuth, URQL, Material UI
- Features:
- Modern React with TypeScript
- Shared types for type-safe forms
- Integration with GraphQL backend
- Responsive design
- Location:
apps/mobile/
- Features:
- Cross-platform iOS/Android/Web
- Expo Router for navigation
- Shared types and utilities
- Type-safe mobile development
Mobile Commands:
cd apps/mobile
# Development
npm run dev # Start Expo dev server
npm run ios # iOS simulator
npm run android # Android emulator
npm run web # Web browser
# Building
npm run build:ios
npm run build:android
- Location:
apps/backend/
- URL: http://localhost:3001/graphql
- Tech Stack: NestJS, GraphQL, Prisma ORM
- Features:
- GraphQL API with type generation
- Prisma ORM for database
- Authentication and authorization
- Auto-generated TypeScript types
# Development (all platforms)
npm run dev # Start backend + frontend + mobile
npm run dev:duo # Start only backend + frontend
# Individual platforms
npm run dev:web # Frontend only
npm run dev:backend # Backend only
npm run dev:mobile # Mobile only
# Mobile specific
npm run start:mobile # Start mobile dev server
npm run build:mobile # Build mobile app
# Setup
npm install # Install all dependencies
npx prisma generate # Generate Prisma client
npx prettier --write . # Format code
Location: packages/shared-types/
Common TypeScript interfaces used across all platforms:
// User types
export interface User {
id: string;
name?: string;
email?: string;
role: string;
createdAt: Date;
updatedAt: Date;
}
export interface CreateUserInput {
name?: string;
email: string;
role?: string;
}
// Post types
export interface Post {
id: string;
title: string;
content?: string;
published: boolean;
authorId?: string;
author?: User;
createdAt: Date;
updatedAt: Date;
}
Location: packages/shared-utils/
Common utility functions available everywhere:
// Validation
export const validateEmail = (email: string): boolean => { /* ... */ }
export const validatePassword = (password: string): boolean => { /* ... */ }
// Formatting
export const formatDate = (date: Date | string): string => { /* ... */ }
export const formatDateTime = (date: Date | string): string => { /* ... */ }
// Pagination
export const calculatePagination = (params: PaginationParams) => { /* ... */ }
1. Define types once (packages/shared-types/src/types.ts
):
export interface CreateUserInput {
name?: string;
email: string;
role?: string;
}
2. Use in Frontend (apps/frontend/components/UserForm.tsx
):
import { CreateUserInput } from '@devplify/shared-types';
const [user, setUser] = useState<CreateUserInput>({
email: '',
name: '',
role: 'user'
});
3. Use in Mobile (apps/mobile/app/profile.tsx
):
import { CreateUserInput } from '@devplify/shared-types';
const [formData, setFormData] = useState<CreateUserInput>({
email: '',
name: '',
role: 'user'
});
4. Use in Backend (apps/backend/src/user/user.service.ts
):
import { CreateUserInput } from '@devplify/shared-types';
async createUser(input: CreateUserInput): Promise<User> {
// Implementation
}
- Single Source of Truth: Types defined once, used everywhere
- Compile-time Errors: Catch issues before runtime
- IntelliSense: Auto-completion across all platforms
- Refactoring Safety: Changes propagate automatically
- Hot Reloading: All platforms update automatically
- Shared Utilities: No code duplication
- Consistent APIs: Same interfaces everywhere
- Easy Debugging: Shared error handling
- Centralized Types: Update once, apply everywhere
- Consistent Validation: Same rules across platforms
- Reduced Bugs: Type system prevents common errors
- Scalable Architecture: Easy to add new platforms
Visit the mobile app's demo screen (/demo
) or web app for interactive examples of:
- โ Type-safe form creation
- โ Shared validation functions
- โ Cross-platform utilities
- โ Auto-completion and error checking
- โ Refactoring safety demonstration
- Add new types: Update
packages/shared-types/src/types.ts
- Add utilities: Update
packages/shared-utils/src/utils.ts
- Build packages:
npm run build
in package directories - Test across platforms: Ensure changes work in web, mobile, and backend
- Maintain type safety: All changes should be type-safe
MIT License - see LICENSE file for details
Ready to build type-safe, cross-platform applications? Get started with npm run dev
! ๐