|
|
2 месяцев назад | |
|---|---|---|
| .agents | 4 месяцев назад | |
| .claude | 4 месяцев назад | |
| apps | 2 месяцев назад | |
| crypto-shim | 2 лет назад | |
| packages | 2 месяцев назад | |
| patches | 3 месяцев назад | |
| scripts | 7 месяцев назад | |
| .cursorrules | 4 месяцев назад | |
| .eslintrc.js | 1 год назад | |
| .gitignore | 2 месяцев назад | |
| .prettierrc.json | 2 лет назад | |
| Dockerfile | 5 месяцев назад | |
| LICENSE | 2 лет назад | |
| agents.md | 2 месяцев назад | |
| animated-icons.md | 4 месяцев назад | |
| claude.md | 7 месяцев назад | |
| package.json | 2 месяцев назад | |
| react-doctor.config.json | 5 месяцев назад | |
| readme.md | 2 месяцев назад | |
| skills-lock.json | 4 месяцев назад | |
| tsconfig.json | 1 год назад | |
| turbo.json | 10 месяцев назад | |
| uniwind.md | 4 месяцев назад | |
| yarn.lock | 2 месяцев назад |
unified cross-platform codebase for web and native applications built with Expo, NextJS, and Uniwind.
NEO Monorepo is a unified codebase providing web and native UI applications for UNA CMS. It enables code sharing between platforms while maintaining platform-specific optimizations.
Key Features:
neo/
├── apps/
│ ├── next/ # Main web application (Next.js 16)
│ └── expo/ # Main native application (Expo 54 / React Native)
│
├── packages/
│ └── app/ # Shared application code (components, lib, design)
│
├── crypto-shim/ # Polyfill for crypto module
├── package.json # Root workspace configuration
├── turbo.json # Turborepo configuration
└── yarn.lock # Dependency lockfile
| App | Purpose | Port | Tech Stack |
|---|---|---|---|
apps/next |
Production web app - Main web interface for UNA | 3000 | Next.js 16, Tailwind CSS 4 |
apps/expo |
Production native app - iOS/Android apps | - | Expo 54, React Native 0.81, Uniwind |
| Package | Purpose |
|---|---|
packages/app |
Shared application code: components, hooks, utilities, design system, settings, translations |
| Technology | Version | Purpose |
|---|---|---|
| React | 19.1.x | UI framework (web 19.1.4 / native 19.1.0) |
| React Native | 0.81.5 | Native mobile framework |
| Expo | 54.0.x | Native development platform |
| Next.js | 16.3.x | Web framework |
| TypeScript | 5.7+ | Type safety |
| Node.js | 24.x | Engines (see root / apps/next package.json) |
| Tailwind CSS | 4.2.x | Styling (web via @tailwindcss/postcss) |
| Uniwind | 1.6.x | Tailwind CSS v4 for React Native (apps/expo) |
| Library | Purpose |
|---|---|
expo-router |
File-based routing for native |
solito |
Cross-platform navigation |
@tanstack/react-query |
Data fetching and caching |
zustand |
State management |
pusher-js |
Real-time WebSocket updates |
react-native-reanimated |
Native animations |
lucide-react / lucide-react-native |
Icons |
engines in root / apps/next package.json)npx expo (for native development)# Clone the repository
git clone <repository-url>
cd neo
# Install all dependencies
yarn
# Create environment configuration
cp .env.example .env.local
Create .env.local in the root directory:
# UNA CMS Configuration
UNA_API_KEY="KEY_FROM_UNA_STUDIO"
UNA_URL=https://api.example.com
NEXT_PUBLIC_UNA_URL=https://api.example.com
# Application URLs
APP_URL=https://example.com
NEXT_PUBLIC_APP_URL=https://example.com
APP_ORIGIN=neo://app
# Server Configuration
PROTO=http:
HOST=localhost
PORT=3000
HTTPS=true
| Command | Description |
|---|---|
yarn web |
Start Next.js web app (port 3000) |
yarn native |
Start Expo dev server for native apps |
yarn ios |
Run native app on iOS simulator |
yarn android |
Run native app on Android emulator |
yarn ios:device |
Run native app on physical iOS device |
| Command | Description |
|---|---|
yarn build |
Build Next.js production bundle |
yarn analyze |
Analyze bundle size |
| Command | Description |
|---|---|
yarn prod |
Start production server (single instance) |
yarn prod:pm2 |
Start production server with PM2 (clustered) |
| Command | Description |
|---|---|
yarn clean |
Remove all node_modules directories |
# Navigate to expo app
cd apps/expo
# Build dev client
expo run:ios # iOS
expo run:android # Android
# EAS Build (cloud)
eas build --platform ios
eas build --platform android
The project uses a layered configuration approach separating main/default files (should not be modified in branches) from custom files (safe to modify in branches).
These files contain the base configuration and should only be modified in the main NEO repository:
| File | Purpose |
|---|---|
packages/app/settings-default.js |
Default application settings |
packages/app/translation-default.js |
Default translations |
packages/app/static-default.js |
Default static content |
packages/app/icons.default.js |
Default icon mappings |
packages/app/icons-svg.default.js |
Default SVG icons |
packages/app/design/tailwind/theme.js |
Main Tailwind theme |
packages/app/loading.default.js |
Default loading components |
packages/app/lib/functions/functions-default.js |
Default utility functions |
packages/app/components/*/\_map_default.js |
Default component mappings |
These files are designed for customization in branch/client projects:
| File | Purpose |
|---|---|
packages/app/settings.js |
Override settings |
packages/app/translation.js |
Override translations |
packages/app/static.js |
Override static content |
packages/app/icons.js |
Override/add icons |
packages/app/icons-svg.js |
Override/add SVG icons |
packages/app/design/tailwind-custom/theme.js |
Custom Tailwind theme |
packages/app/loading.js |
Override loading components |
packages/app/lib/functions/functions.js |
Override utility functions |
packages/app/components/*/\_map.js |
Override component mappings |
apps/expo/app.config.custom.js |
Native app build configuration |
apps/next/next.config.custom.js |
Next.js custom configuration |
Override settings in packages/app/settings.js:
import { settingsDefault } from './settings-default';
// Override specific settings
settingsDefault.layout.defaults.name = 'ver';
settingsDefault.app.title = 'My App';
export const settings = settingsDefault;
Override translations in packages/app/translation.js:
import { resourcesDefault } from './translation-default';
resourcesDefault.en.translation['bx_market_reviews_title'] = 'Reviews';
resourcesDefault.en.translation['custom_key'] = 'Custom Value';
export const resources = resourcesDefault;
Customize theme in packages/app/design/tailwind-custom/theme.js:
const colors = {
bgrcard: {
DEFAULT: '#ffffff',
d: '#1a1a1a',
},
// Add custom colors...
};
const theme = {
extend: {
colors: colors,
// Add custom theme extensions...
},
};
module.exports = { theme, colors };
packages/app/icons.js)'use client'
import { IconSet as IconSetDefault } from './icons.default';
import { Airplane } from 'lucide-react-native';
export const IconSet = {
'Airplane': Airplane,
...IconSetDefault
};
packages/app/icons-svg.js)'use client'
import * as SvgIconsDef from 'app/icons-svg.default';
import Svg, { Path } from 'react-native-svg';
const CustomIcon = ({ width = "100%", height = "100%", color = "#868686" }) => (
<Svg width={width} height={height} viewBox="0 0 24 24" fill="none">
<Path d="M12 2L2 7l10 5 10-5-10-5z" fill={color} />
</Svg>
);
export default {
...SvgIconsDef,
CustomIcon
};
Customize apps/expo/app.config.custom.js:
module.exports = {
name: "My App",
owner: "myorg",
slug: "my-app",
scheme: "myapp",
version: "1.0.0",
icon: "./assets/custom/icon.png",
splash: {
image: "./assets/custom/splash.png",
backgroundColor: "#ffffff",
},
ios: {
bundleIdentifier: "com.myorg.myapp",
buildNumber: "1",
},
android: {
package: "com.myorg.myapp",
versionCode: 1,
},
extra: {
eas: { projectId: "your-project-id" },
UNA_API_KEY: "your-api-key",
NEXT_PUBLIC_UNA_URL: "https://api.yoursite.com",
UNA_URL: "https://api.yoursite.com",
},
};
Customize apps/next/next.config.custom.js:
const nextConfigCustom = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'yourdomain.com',
pathname: '**',
},
],
},
};
module.exports = nextConfigCustom;
Override components by creating custom files and updating the _map.js file:
packages/app/ui/molecules/custom/my-component.jsUpdate packages/app/ui/molecules/_map.js:
import { componentsMapDefault } from './_map_default';
import MyComponent from 'app/ui/molecules/custom/my-component';
componentsMapDefault['my-component'] = MyComponent;
export const componentsMap = componentsMapDefault;
| Asset Type | Location |
|---|---|
| Favicon | apps/next/public/static/favicon.svg (or .ico via customization) |
| Manifest | apps/next/public/static/manifest.json |
| SVG Images | apps/next/public/svg/local/ |
| App Icons | apps/expo/assets/ |
.gitignore for Branch ProjectsWhen creating a branch/client project, add these entries to .gitignore to prevent modifying main repository files:
# ===================================
# PROTECT MAIN REPOSITORY FILES
# ===================================
# Settings defaults (modify settings.js instead)
packages/app/settings-default.js
# Translation defaults (modify translation.js instead)
packages/app/translation-default.js
# Static defaults (modify static.js instead)
packages/app/static-default.js
# Icon defaults (modify icons.js instead)
packages/app/icons.default.js
packages/app/icons-svg.default.js
# Loading defaults (modify loading.js instead)
packages/app/loading.default.js
# Main theme (modify tailwind-custom/theme.js instead)
packages/app/design/tailwind/theme.js
# Default component maps (modify _map.js instead)
packages/app/components/**/_map_default.js
packages/app/ui/**/_map_default.js
# Function defaults (modify functions.js instead)
packages/app/lib/functions/functions-default.js
# Feed items defaults
packages/app/lib/feed-items_default.js
# ===================================
# ALLOWED CUSTOM FILES (DO NOT IGNORE)
# ===================================
# packages/app/settings.js
# packages/app/translation.js
# packages/app/static.js
# packages/app/icons.js
# packages/app/icons-svg.js
# packages/app/loading.js
# packages/app/design/tailwind-custom/theme.js
# packages/app/components/**/_map.js
# packages/app/ui/**/_map.js
# packages/app/lib/functions/functions.js
# apps/expo/app.config.custom.js
# apps/next/next.config.custom.js
*-default.js or main configuration filesThe web app is configured for Vercel with apps/next/vercel.json:
{
"framework": "nextjs",
"installCommand": "cd ../.. && yarn install",
"buildCommand": "yarn build",
"outputDirectory": ".next"
}
Steps:
apps/next# Build the application
yarn build
# Start production server
yarn prod
# Install PM2 globally
npm install -g pm2
# Build and start with PM2
yarn build
yarn prod:pm2
PM2 configuration in apps/next/pm2.config.js:
pm2 list # View running processes
pm2 logs neoapp # View logs
pm2 restart neoapp # Restart application
pm2 stop neoapp # Stop application
pm2 delete neoapp # Remove from PM2
cd apps/expo
# Development build
eas build --profile development --platform ios
eas build --profile development --platform android
# Production build
eas build --profile production --platform ios
eas build --profile production --platform android
# Submit to stores
eas submit --platform ios
eas submit --platform android
cd apps/expo
# iOS (requires macOS + Xcode)
expo run:ios --configuration Release
# Android
expo run:android --variant release
NEO uses a hybrid routing strategy:
expo-router in apps/expo/app/apps/next/app/solito for shared navigation patternsAgent and UNA integration guidance (including routing context) lives in agents.md at the repo root and in the una-api skill.
cd apps/expo
yarn add package-name
cd ../..
yarn
Then add to transpilePackages in apps/next/next.config.js:
transpilePackages: [
'react-native',
'react-native-web',
'package-name', // Add here
// ...
]
cd apps/next
yarn add package-name
cd ../..
yarn
cd apps/expo
yarn add package-name
cd ../..
yarn
| Issue | Solution |
|---|---|
| Module not found | Run yarn clean && yarn |
| Metro bundler cache | Run yarn native --clear |
| Next.js cache | Delete .next folder and rebuild |
| iOS pods outdated | cd apps/expo/ios && pod install |
| Type errors | Run yarn typecheck to identify issues |
# Check workspace dependencies
yarn workspaces info
# Analyze bundle
yarn analyze
# Clean all caches
yarn clean
rm -rf apps/expo/.expo
rm -rf apps/next/.next
yarn
See LICENSE for details.