Skip to content

pinely-international/react-native-mobx-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

The Best React-native + Mobx architecture template πŸ‘‘


🏁 Quick Start

  1. git clone https://github.com/aianov/react-native-mobx-template
  2. bun i (or yarn or npm i) [bun prefered]
  3. npx expo start

About architecture:

Well... There is too much to explain and talk about



First thing, let's talk about architecture.


πŸ“ Architecture

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 23 22 21

Pretty empty right?

We have app, assets, core and modules folders inside src folder.


πŸ“‚ SRC folders explain:

src/
β”œβ”€β”€ __tests__/     # For components, functions, screenshot and etc all type of tests [I use Jest btw]
β”œβ”€β”€ app/        # Have `main.tsx`, and `App.tsx`. Also folders like `layouts` and `router`.
β”œβ”€β”€ assets/         # Inside this folder we have 6 folders with animations, fonts, icons, images, sounds, and global styles from StyleSheet
β”œβ”€β”€ core/           # One of the important folder here. Inside we have folders like: api, config, hooks, lib, locales and etc We will talk about this folder later.
β”œβ”€β”€ modules/       # Now I'll start to show you unique architecture.

Some kind of folders are too easy and small to explain, so I will skip folders sometime


πŸ”₯ Now Let's dive deeper into each folder!


βš™οΈ core/ folder - THE BRAIN 🧠

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 22 04 03

This is where magic happens. Let me show you structure first:

core/
β”œβ”€β”€ api/              # API configuration
β”œβ”€β”€ config/           # App constants, types, regex, functions
β”œβ”€β”€ hooks/            # Custom React hooks (global)
β”œβ”€β”€ lib/              # πŸ”₯ The most important - all utilities
β”œβ”€β”€ locales/          # i18n translations (en, ru)
β”œβ”€β”€ storage/          # AsyncStorage wrappers
β”œβ”€β”€ stores/           # MobX global stores
β”œβ”€β”€ ui/               # 🎨 Reusable UI components
β”œβ”€β”€ utils/            # Small utility functions
└── widgets/          # Complex reusable widgets

Let's go through each one...


πŸ“‘ core/api/

api/
└── api.ts            # HTTP instance configuration

Here we configure our HTTP client. Base URL, interceptors, headers - everything. Using our own axios like function, which helps us to use mobxSaiFetch function with DebuggerUi [We'll talk about this later]


βš™οΈ core/config/

config/
β”œβ”€β”€ constants.ts      # App-wide constants
β”œβ”€β”€ functions.ts      # Helper functions
β”œβ”€β”€ regex.ts          # Regex patterns
└── types.ts          # Global TypeScript types

All your app configuration in one place. Constants like API endpoints, regex for validation, global types. Base show, u can do whatever you want here


πŸ“š core/lib/ - THE LIBRARY'S πŸ“–

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 22 08 20

This is where all the magic utilities live:

lib/
β”œβ”€β”€ arr/              # Array utilities (empty, ready for use)
β”œβ”€β”€ date/             # Date formatting functions
β”œβ”€β”€ debuggerUi/       # πŸ”₯ Built-in debugger UI component
β”œβ”€β”€ global/           # Global extensions (Array.prototype, etc.)
β”œβ”€β”€ helpers/          # General helper functions
β”œβ”€β”€ mobx-toolbox/     # πŸ”₯ MobX utilities (THE CORE)
β”‚   β”œβ”€β”€ mobxDebouncer/    # I think the best Debouncer ever written on MobX to any actions
β”‚   β”œβ”€β”€ mobxSaiFetch/     # HTTP requests with MobX (like React Query but much better)
β”‚   β”œβ”€β”€ mobxState/        # Easy state creation
β”‚   β”œβ”€β”€ mobxValidator/    # Form validation
β”‚   β”œβ”€β”€ useMobxForm/      # Form management
β”‚   └── useMobxUpdate/    # State updates helper [U'll never will use it because its in mobxSaiFetch function inside]
β”œβ”€β”€ navigation/       # Navigation utilities and hooks
β”œβ”€β”€ notifier/         # Toast notifications system
β”œβ”€β”€ numbers/          # Number formatting
β”œβ”€β”€ obj/              # Object utilities
β”œβ”€β”€ performance/      # Performance hooks (debounce, optimized callbacks)
β”œβ”€β”€ string/           # String utilities
β”œβ”€β”€ text/             # Text formatting and components
└── theme/            # Theme utilities (colors, gradients)

Most important here is πŸ”₯ mobx-toolbox/ πŸ”₯ :

  • mobxSaiFetch - like React Query but for MobX. Caching, optimistic updates, infinite scroll - everything!
  • mobxState - create MobX state in one line
  • mobxValidator - validation schemas like Zod but simpler
  • useMobxForm - form management with validation
  • useMobxUpdate - update nested state easily

🌍 core/locales/

locales/
β”œβ”€β”€ en/
β”‚   └── translation.json
└── ru/
    └── translation.json

i18n translations. Just add new language folder and translation.json file.


πŸ’Ύ core/storage/

storage/
β”œβ”€β”€ AppStorage.ts     # App-specific storage
β”œβ”€β”€ CacheManager.ts   # Cache management
β”œβ”€β”€ index.ts          # Main export
└── types.ts          # Storage types

AsyncStorage wrappers. Easy to use, type-safe.


πŸͺ core/stores/

stores/
β”œβ”€β”€ global-interactions/    # Global app interactions
β”‚   β”œβ”€β”€ global-interactions/
β”‚   └── route-interactions/
└── memory/                 # Memory management
    β”œβ”€β”€ memory-interactions/
    └── memory-services/

Global MobX stores. Things that need to be accessed from anywhere.


🎨 core/ui/ - UI COMPONENTS LIBRARY

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 22 12 42

Holy... we have a lot here:

ui/
β”œβ”€β”€ AnimatedTabs/         # Animated tab component
β”œβ”€β”€ AnimatedTransition/   # Page transitions
β”œβ”€β”€ AsyncDataRender/      # Render based on async state
β”œβ”€β”€ BgWrapperUi/          # Background wrapper
β”œβ”€β”€ BlurUi/               # Blur effect
β”œβ”€β”€ BottomSheetUi/        # Bottom sheet modal
β”œβ”€β”€ BoxUi/                # Flexbox wrapper (like Box in MUI)
β”œβ”€β”€ ButtonUi/             # Button component
β”œβ”€β”€ CheckboxUi/           # Checkbox
β”œβ”€β”€ CleverImage/          # Smart image with caching
β”œβ”€β”€ ContextMenuUi/        # Context menu
β”œβ”€β”€ CustomRefreshControl/ # Pull to refresh
β”œβ”€β”€ DatePickerUi/         # Date picker
β”œβ”€β”€ ErrorTextUi/          # Error text display
β”œβ”€β”€ FormattedText/        # Text with formatting
β”œβ”€β”€ GridContentUi/        # Grid layout
β”œβ”€β”€ GroupedBtns/          # Button group
β”œβ”€β”€ HoldContextMenuUi/    # Long press context menu
β”œβ”€β”€ ImageSwiper/          # Image carousel
β”œβ”€β”€ InputUi/              # Text input
β”œβ”€β”€ LiveTimeAgo/          # "5 min ago" component
β”œβ”€β”€ LoaderUi/             # Loading spinner
β”œβ”€β”€ MainText/             # Main text component
β”œβ”€β”€ MediaPickerUi/        # Image/video picker
β”œβ”€β”€ Modal/                # Modal component
β”œβ”€β”€ ModalUi/              # Another modal variant
β”œβ”€β”€ PageHeaderUi/         # Page header
β”œβ”€β”€ PhoneInputUi/         # Phone number input
β”œβ”€β”€ PressableUi/          # Pressable wrapper
β”œβ”€β”€ RefreshControlUi/     # Refresh control
β”œβ”€β”€ SecondaryText/        # Secondary text
β”œβ”€β”€ SelectImageUi/        # Image selector
β”œβ”€β”€ Separator/            # Divider line
β”œβ”€β”€ SimpleButtonUi/       # Simple button
β”œβ”€β”€ SimpleInputUi/        # Simple input
β”œβ”€β”€ SimpleModalUi/        # Simple modal
β”œβ”€β”€ SimpleTextAreaUi/     # Simple textarea
β”œβ”€β”€ SkeletonUi/           # Skeleton loading
β”œβ”€β”€ SwitchUi/             # Toggle switch
β”œβ”€β”€ TextAreaUi/           # Textarea
β”œβ”€β”€ index.ts              # All exports
└── types.ts              # UI types

Every component you need is here. All themed, all customizable from src/modules/theme/stores/theme-interactions.


πŸ› οΈ core/utils/

utils/
β”œβ”€β”€ device-info.ts    # Device information
β”œβ”€β”€ haptics.ts        # Haptic feedback
β”œβ”€β”€ jwt.ts            # JWT utilities
└── notifications.ts  # Push notifications

Small utility functions. Nothing fancy, just useful stuff.


🧩 core/widgets/

widgets/
└── wrappers/
    └── MainWrapper/  # Main app wrapper

Complex reusable widgets. Wrappers, compound components, etc.


πŸ“¦ modules/ folder - FEATURE MODULES

modules/
β”œβ”€β”€ auth/             # Authentication module
β”‚   β”œβ”€β”€ pages/        # Auth screens
β”‚   β”œβ”€β”€ shared/       # Shared auth components
β”‚   β”œβ”€β”€ stores/       # Auth MobX stores
β”‚   └── widgets/      # Auth widgets
β”œβ”€β”€ onboarding/       # Onboarding module
β”‚   β”œβ”€β”€ pages/
β”‚   β”œβ”€β”€ shared/
β”‚   └── stores/
└── theme/            # Theme module
    └── stores/       # Theme MobX store

Each module has same structure:

  • pages/ - screens/pages
  • shared/ - shared components for this module
  • stores/ - MobX stores for this module in S.A.I Architecture
  • widgets/ - complex widgets for this module

This is Feature-Sliced Design but simpler. Each feature is isolated. Easy to understand, easy to maintain.


stores/ folders - S.A.I Architecture

S - Services

A- Actions

I - Interactions

All logic of all features, need to be separated to this 3 main stores

auth/
β”œβ”€β”€ stores/                 # Authentication module
β”‚   β”œβ”€β”€ auth-actions/       # Actions store - only requests function and response states [mobxSaiFetch function here]
β”‚   β”œβ”€β”€ auth-interactions/  # Interactions store - All interaction logic with JSX
β”‚   β”œβ”€β”€ auth-service/       # Services store - Boilerplate from interactions and actions, etc: success & error handlers for action store
β”‚	β”‚
β”‚   └── index.ts/           # Re-export for best path-alias experience and clean code

That's it for architecture!


πŸ”₯ DebuggerUi - Built-in Debug Panel

This is probably one of the coolest features you've ever seen. A floating draggable debug panel that shows everything happening in your app in real-time.

What it looks like:

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 23 36 50

A small floating React icon button that you can drag anywhere on screen. Tap it to open the full this debug panel:

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 21 28 15

Features:

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 21 28 54

πŸ“‘ Requests Tab

Shows all HTTP requests with:

  • Request/Response data with syntax highlighting
  • CACHED tag (yellow border) - data from local memory cache
  • LOCAL-CACHED tag (purple border) - data from localStorage
  • NO-PENDING tag - request made without loading state
  • FORCE-FETCH tag - forced fresh request
  • Repeat count (Γ—3 means same request was made 3 times)
  • Copy button for each request
Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 21 29 19

πŸ“¦ Cache Tab

Shows current in-memory cache:

  • All cached entries with their keys
  • Data preview
  • Delete individual cache items
  • Clear all cache
Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 21 29 28

πŸ“ Logger Tab

Real-time logs with colors:

  • Info (blue)
  • Success (green)
  • Warning (orange)
  • Error (red)
  • Copy last 100 logs button
  • Or press to any log to copy one
  • Auto-scroll to bottom
Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2025-12-01 Π² 21 29 42

πŸ’Ύ LocalStorage Tab

Shows all AsyncStorage data:

  • Key-value pairs
  • Array length indicators
  • Delete individual items

πŸ–ΌοΈ Images Tab

Shows cached images from storage


πŸ”„ Cache Updates Tab

Shows history of all cache mutations:

  • saiUpdater - in-memory updates
  • saiLocalCacheUpdater - local cache updates
  • saiLocalStorageUpdater - localStorage updates
  • Shows what changed (added/removed items, changed keys)

πŸ” Global Search

Search across ALL tabs at once! Find any string in:

  • Request URLs
  • Request/Response bodies
  • Cache data
  • LocalStorage
  • Navigate between matches

Font Size Controls

Each tab has +/- buttons to adjust font size. Saved to localStorage! [Press DEFF to return default font size]


Basic usage [Already in template]:

// In your App.tsx or root component
import { DebuggerUi } from '@lib/debuggerUi/DebuggerUi';

export const AppContent = () => {
  return (
    <>
      {__DEV__ && <DebuggerUi />}  {/* Only show in development */}
    </>
  );
};

export const App = () => {
	return (
		<AppContent />
	)
}

That's it! Now you have full visibility into your app's HTTP layer πŸ”₯


πŸ”₯ mobxSaiFetch - HTTP Requests with Superpowers

This is the heart of the template. Like React Query, but for MobX. Actually, I think it's even better.

Basic Usage:

// In your store
class UserActionsStore {
	constructor() { makeAutoObservable(this); }

	profile: MobxSaiFetchInstance<GetProfileResponse> = {}

	getProfileAction = () => {
		profile = mobxSaiFetch(
			`/user/profile/${userId}`,               // URL
			null,                                    // Body {} (null for GET)
			{
      			id: 'getUserProfile',                // Cache key
      			storageCache: true,                  // Save to AsyncStorage
      			onSuccess: getProfileSuccessHandler, // Success callback
				onError: getProfileErrorHandler      // Error callback
    		}
		);
	}
}

In your component:

import { observer } from 'mobx-react-lite';
import { AsyncDataRender } from '@core/ui';

export const ProfileScreen = observer(() => {
  	const {
		profile: { status, data }
	} = userStore;

  	return (
		<AsyncDataRender
			status={status}
			data={data}
			emptyComponent={<ProfileEmpty />} // U can customize or make by default in AsyncDataRender core/ui
			errorComponent={<ProfileError />} // On error component fallback
			refreshControllCallback={onRefresh}
			renderContent={() => {
				return <ProfileCard data={profile.data} />
			}
		/>
  	);
});

All Status Fields:

interface MobxSaiFetchInstance<T> {
  // Data
  data: T | null;
  error: Error | null;
  body: any;
  
  // Main status
  status: "pending" | "fulfilled" | "rejected";
  isPending: boolean;
  isFulfilled: boolean;
  isRejected: boolean;
  
  // Scope status (for infinite scroll)
  scopeStatus: "pending" | "fulfilled" | "rejected" | "";
  isScopePending: boolean;
  isScopeFulfilled: boolean;
  isScopeRejected: boolean;
  
  // Top/Bottom loading (infinite scroll)
  isTopPending: boolean;
  isBotPending: boolean;
  isHaveMoreTop: { isHaveMoreTop: boolean };
  isHaveMoreBot: { isHaveMoreBot: boolean };
  
  // Methods
  fetch: (promise) => this;
  reset: () => this;
  saiUpdater: (...) => void; // its basically useMobxUpdate instance (Can update cache too, for sync with local data)
}

Options:

mobxSaiFetch(url, body, {
  // Required
  id: 'uniqueCacheKey',              // Cache identifier
  
  // HTTP
  method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH',
  headers: { 'X-Custom': 'value' },
  timeout: 5000,
  
  // Caching
  storageCache: true,                // Persist to AsyncStorage
  takeCachePriority: 'localStorage', // 'localStorage' | 'localCache'
  
  // Behavior
  fetchIfPending: false,             // Skip if already loading
  fetchIfHaveData: true,             // Re-fetch even if data exists
  needPending: true,                 // Show loading state
  shadowFirstRequest: true,          // First request updates cache silently
  
  // Data extraction
  takePath: 'data.user',             // Extract nested data
  pathToArray: 'items',              // Path to array for updates
  
  // Callbacks
  onSuccess: (data, body) => {},
  onError: (error) => {},
  onCacheUsed: (data, body, priority) => {},
  
  // Infinite Scroll
  dataScope: {
    scrollRef: flatListRef,          // For React Native
    topPercentage: 20,               // Trigger top fetch at 20%
    botPercentage: 80,               // Trigger bottom fetch at 80%
    startFrom: 'top' | 'bot',        // Initial position
    relativeParamsKey: 'cursor',     // Param for pagination
    isHaveMoreResKey: 'hasMore',     // Response field for more data
    setParams: setParams,            // State setter for params
    scopeLimit: 100,                 // Max items in memory
  },
  
  // Add fetched data to array
  fetchAddTo: {
    path: 'messages',                // Array path
    addTo: 'start' | 'end',          // Where to add new data
  },
  
  // Optimistic Updates
  optimisticUpdate: {
    enabled: true,
    createTempData: (body) => ({
      id: `temp_${Date.now()}`,
      ...body,
      isTemp: true,
    }),
    targetCacheId: 'getMessages',
  }
});

createMobxSaiHttpInstance - Axios like but just only for mobxSaiFetch usage

! To use mobxSaiFetch with "baseUrl" setted. You need to use createMobxSaiHttpInstance. !

Basic usage:

import { createMobxSaiHttpInstance } from '@lib/mobx-toolbox';
import { Platform } from 'react-native';

export const createInstance = () => {

	const mobxHttpInstance = createMobxSaiHttpInstance({
		baseURL,
		withCredentials: true,
		headers: {
			'Content-Type': 'application/json'
		}
	});

	mobxHttpInstance.defaults.withCredentials = true;

	mobxHttpInstance.interceptors.request.use(
		async (config) => {
			config.withCredentials = true;        // ALL REQUESTS
			return config;
		},
		(error: any) => {
			console.error(error)                  // ALL ERRORS
			return Promise.reject(error);
		}
	);

	mobxHttpInstance.interceptors.response.use(
		async (response) => {
			console.log(response);                 // ALL RESPONSES
			return response;
		},
		(error: any) => {
			console.error(error);                  // ALL ERRORS FROM RESPONSES
			return Promise.reject(error);
		}
	);

	return mobxHttpInstance;
};

It's only needed for set baseurl to more comfy mobxSaiFetch usage (1-st param)


Updating Cached Data:

Method 1: saiUpdater (on instance)

const { messages } = messageActionsStore

// Update single item in array
messages.saiUpdater(
  'message-123',              // ID of item to update
  'isRead',                   // Field to update [TYPE SAFE]
  true,                       // New value
  'id',                       // ID field name
  'getMessages',              // Cache ID
  'both'                      // Update both caches
);

// Update with function
messagesStore.messages.saiUpdater(
  'message-123',
  'likes',
  (prev) => prev + 1,
  'id',
  'getMessages',
  'localStorage'
);

// Update entire array
messagesStore.messages.saiUpdater(
  null,                              // null = update array
  null,
  (prevArray) => prevArray.filter(m => !m.isDeleted),
  'id',
  'getMessages',
  'both'
);

Method 2: Global cache updaters

import { 
  saiLocalCacheUpdater,
  saiLocalStorageUpdater,
  saiCacheUpdater 
} from '@lib/mobx-toolbox';

// Update in-memory cache
await saiLocalCacheUpdater('getMessages', (currentData) => {
  return {
    ...currentData,
    messages: currentData.messages.filter(m => m.id !== deletedId)
  };
});

// Update localStorage
await saiLocalStorageUpdater('getMessages', (currentData) => {
  return { ...currentData, unreadCount: 0 };
});

// Update both at once
await saiCacheUpdater('getMessages', (currentData) => {
  return { ...currentData, lastSeen: Date.now() };
});

Infinite Scroll Example:

// In getMessagesAction function:

const MESSAGES_LIMIT = 50

params = mobxState({
	chat_id: "...",
	relative_id: null,
	up: true,
	limit: MESSAGES_LIMIT
})("params")
  
messages = mobxSaiFetch(
   '/chat/messages',
   params.params,
   {
      id: 'getChatMessages',
      pathToArray: 'messages',
      takeCachePriority: "localStorage",
      method: 'GET',
      needPending,
      fetchIfPending: false,
      fetchIfHaveData: false,
      fetchIfHaveLocalStorage: false,
      storageCache: true,
      onSuccess: getMessagesSuccessHandler,
      onError: getMessagesErrorHandler,
	  maxCacheData: 10,
      dataScope: {
         startFrom: "bot", // Start from bottom (newest)
         scrollRef: messagesScrollRef,
         topPercentage: 80, // Load older when scroll 15% from top
         botPercentage: 20, // Load newer when scroll 85% from top
         setParams: params.setParams,
         relativeParamsKey: "relative_id", // path to "relative_id" key from params to auto-reload for auto fetches in virtual list
         upOrDownParamsKey: "up", // path to "up" key from params
         isHaveMoreResKey: "is_have_more", // path to "is_have_more" key from backend response
         howMuchGettedToTop: 2, // How many pages can load up before scopeLimit start works
         upStrategy: "reversed",
         scopeLimit: MESSAGES_LIMIT * 2 // Keep max 100 messages in memory
      },
      cacheSystem: {
         limit: MESSAGES_LIMIT
      },
      fetchAddTo: {
         path: "messages",
         addTo: "start"
      },
    }
  );
import { LegendList, LegendListRef } from '@legendapp/list';

export const ChatScreen = observer(() => {
	const { messages } = messageActionsStore;
	const { messagesScrollRef: { setMessagesScrollRef } } = messageInteractionsStore;

	const scrollRef = useRef<LegendListRef | null>(null);

	useEffect(() => {
		if (!scrollRef.current) return
		setMessagesScrollRef(scrollRef as any);
	}, [scrollRef.current]);

  	return (
		<LegendList
			ref={scrollRef}
			data={processedMessages}
			renderItem={renderItem}
			keyExtractor={keyExtractor}
			contentContainerStyle={contentContainerStyle}
			maintainVisibleContentPosition={true}
			recycleItems={false}
			drawDistance={500}
			estimatedItemSize={100}
			getEstimatedItemSize={getEstimatedItemSize}
			stickyIndices={Platform.OS === 'ios' ? stickyHeaderIndices : undefined}
			viewabilityConfig={viewabilityConfig}
			onScroll={handleScrollInternal}
			onMomentumScrollBegin={handleMomentumScrollBegin}
			scrollEventThrottle={16}
			keyboardShouldPersistTaps='handled'
			keyboardDismissMode='interactive'
			bounces={true}
		/>
  	);
});

Check Cache Existence:

import { hasSaiCache } from '@lib/mobx-toolbox';

// Check if data exists in any cache
const hasCache = await hasSaiCache('all', 'getUserProfile'); // Usefull for needPending option

// Check specific cache types
const hasLocalCache = await hasSaiCache(['localCache'], 'getUserProfile');
const hasStorage = await hasSaiCache(['localStorage'], 'getUserProfile');
const hasData = await hasSaiCache(['data'], userStore.profile);

🎨 Theming System

Full theming support with MobX reactivity. Change theme - UI updates instantly.

Theme Structure:

// All available theme tokens
interface ThemeT {
  // Backgrounds
  bg_000: string;  // Lightest
  bg_100: string;
  bg_200: string;
  bg_300: string;
  bg_400: string;
  bg_500: string;
  bg_600: string;  // Darkest (no really always)
  
  // Borders (converted from CSS to RN format)
  border_100: string;
  border_200: string;
  // ...
  
  // Border radius (numbers for RN)
  radius_100: number;  // 20
  radius_200: number;  // 15
  // ...
  
  // Button backgrounds
  btn_bg_000: string;
  btn_bg_100: string;
  // ...
  
  // Button heights (numbers)
  btn_height_100: number;  // 55
  btn_height_200: number;  // 50
  // ...
  
  // Colors
  primary_100: string;   // Blue shades
  primary_200: string;
  primary_300: string;
  
  success_100: string;   // Green shades
  success_200: string;
  success_300: string;
  
  error_100: string;     // Red shades
  error_200: string;
  error_300: string;
  
  // Text
  text_100: string;      // Main text color
  secondary_100: string; // Secondary text
  
  // Inputs
  input_bg_100: string;
  input_border_300: string;
  input_height_300: number;
  input_radius_300: number;
  
  // Gradient
  mainGradientColor: {
    background: string;  // CSS gradient
  };
}

Using Theme in Components:

import { Box, MainText } from "@core/ui";
import { observer } from 'mobx-react-lite';
import { themeStore } from '@modules/theme/stores';

export const MyComponent = observer(() => {
  const { currentTheme } = themeStore;
  
  	return (
    	<Box
			bRad={currentTheme.radius_300} // Here
			bgColor={currentTheme.bg_100} // Here
		>
			// Text components from @core/ui already connected to currentTheme ;)
      	<MainText>
        		Hello World! MainText using currentTheme.text_100!
      	</MainText>
    	</Box>
  );
});

Changing Theme:

// Change entire theme
themeStore.changeTheme({
  bg_000: "rgba(18, 18, 18, 1)",
  bg_100: "rgba(24, 24, 24, 1)",
  text_100: "rgba(255, 255, 255, 1)",
  // ... dark theme values
});

// Change single value
themeStore.setThemeValue('primary_100', 'rgba(255, 0, 0, 1)');

// Set complete theme object
themeStore.setCurrentTheme(darkTheme);

Creating Dark Theme:

const darkTheme: ThemeT = {
  bg_000: "rgba(0, 0, 0, 1)",
  bg_100: "rgba(18, 18, 18, 1)",
  bg_200: "rgba(28, 28, 28, 1)",
  bg_300: "rgba(38, 38, 38, 1)",
  // ...
  
  text_100: "rgba(255, 255, 255, 1)",
  secondary_100: "rgba(156, 156, 156, 1)",
  
  border_100: "rgba(48, 48, 48, 1)",
  // ...
};

// Apply it
themeStore.changeTheme(darkTheme);

Theme in UI Components:

All core/ui components automatically use theme:

// ButtonUi uses theme colors
<ButtonUi 
  text="Click me" 
  onPress={handlePress}
  // Uses theme.primary_100 by default
/>

// InputUi uses theme
<InputUi
  placeholder="Enter text"
  // Uses theme.input_bg_100, theme.input_border_300, etc.
/>

πŸ”§ Other Utilities

logger - Colored Logging

All logs appear in DebuggerUi in Logger tab

import { logger } from '@lib/helpers';

logger.info('Component', 'User clicked button');
logger.success('API', 'Data loaded successfully');
logger.warning('Cache', 'Cache miss, fetching...');
logger.error('Network', 'Request failed');

Navigation Hooks

import { navigate } from '@lib/navigation';

class SomeClass {
	constructor() { makeAutoObservable(this) };

	someFunction = () => {
		navigate("SignIn") // Use navigate in MobX

		// Yes, you can use navigate function from .ts files
		// Outside components. Everywhere!
	}
}

Create your first module:

modules/your-feature/
β”œβ”€β”€ pages/
β”‚   └── YourPage/
β”‚       └── YourPage.tsx
β”œβ”€β”€ stores/
β”‚   β”œβ”€β”€ your-actions/
β”‚   β”‚   └── your-actions.ts    # HTTP requests
β”‚   β”œβ”€β”€ your-interactions/
β”‚   β”‚   └── your-interactions.ts  # UI logic
β”‚   β”œβ”€β”€ your-service/
β”‚   β”‚   └── your-service.ts    # Business logic
β”‚   └── index.ts # Re-exports
β”œβ”€β”€ widgets/
β”‚   └── YourWidget/
β”œβ”€β”€ shared/
β”‚	 └── config/
β”‚	 └── schemas/
β”‚	 └── idk/
β”œβ”€β”€ hooks/
β”œβ”€β”€ components/
β”œβ”€β”€ etc.../

And remember. It's all CUSTOMIZIBLE.

You can change whatever you want, lib, ui, or something else.


That's the architecture! Simple, scalable, maintainable and very satisfying.

Just-Perfect πŸ’Ž


πŸ“ž Contact

Telegram: @nics51

Questions? Issues? Feature requests? Hit me up! [Or create an issue]


Made with ❀️ and lots of πŸ§ƒ from Kazakhstan πŸ‡°πŸ‡Ώ for Pinely ✨

About

Powerful architecture for MobX React-native development

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published