Monorepos in Action 

Lessons from React & React Native Development

@GeekDay 2025

About Me

  • React / React Native Development Lead at Innovance Consultancy
  • Hobbies
    • Scuba diving
    • Rowing
    • Metal music \m/
  • Links
    • medium: @ozgunbal
    • linkedin: in/ozgunbal
    • GitHub: ozgunbal

Özgün Bal

Contents

  • What's monorepo
  • Myths and facts
  • Monorepo tools
  • Use case: React & React Native Development
  • Lessons learned

What's Monorepo?

A monorepo is a single repository containing multiple distinct projects, with well-defined relationships

Other terms

  • Polyrepo(multi-repo): smaller repositories or components that often have a singular responsibility
  • Monolith: managed by only one git repo and all features, utils and services are coupled
  • Code colocation: several projects in single repository

Myths and Facts

  • Forces us to release together. Monoliths are bad
    • NOT! -> Independent deployments, monorepo != monolith
  • Other teams will change my code without my knowing
    • NOT! -> many tools let you configure ownership on the folder basis
  • Doesn’t scale
    • Dependent packages doesn't change too much to affect all projects

Monorepo tools

  • Lerna 
  • Lage
  • Nx
  • Turborepo
  • etc.

Use case: React & React Native Development

  • Mostly same business logic
  • Consumes same APIs
  • Preventing code duplication
  • Single responsible team

What about react-native-web?

  • Past unpleasant DX
  • Maybe valid in 2025(?)
  • Expo can be a replacement
  • Small and less native orientend project can be viable

Project/library structure

  • api: All typescript api definitions and interfaces generated with codegen
  • shared: business rules (data acquisition, form management and mutations)
  • app-specific:
    • navigation
    • view components
    • platform specific controls

Shared custom hooks

const useSharedHook = (...arguments) => {
  const api = useApi()
  const form = useForm();

  const someHandler = () => {
    // Does some stuff
  };

  return { relevantDataToBeUsedInViews };
};
// React.js

const FormPage: FC = () => {
  const navigate = useNavigate();
  const { data } = useSharedHook();
  
  const handleNavigate = () => {
    navigate('/other-page');
  };

  return (
    <div>
      <header>Title</header>
      {data}
      <button onClick={handleNavigate}>
        Navigate
      </button>
    </div>
  )
}
// React Native

const FormPage: FC = () => {
  const { navigate } = useNavigation();
  const { data } = useSharedHook();
  
  const handleNavigate = () => {
    navigate('/other-page');
  };

  return (
    <View>
      <View>Title</View>
      {data}
      <Button onPress={handleNavigate}>
        Navigate
      </Button>
    </View>
  )
}

Common Configuration 

  • Typescript
  • ESLint
  • Prettier
  • Stylelint
  • PR pipeline check

Code Review Concerns

  • Is this change affect other apps?
  • Should it be placed inside the app or shared library 
  • Is specific bugfix can be applied to other apps?
  • Package upgrades
  • Labeling for effects

CI/CD

  • Easier to manage
  • Multiple app or library can be run at once
  • Drawbacks:
    • Unintended package install for other app's dependencies

Lessons Learned

  • Single team maintaining single repository is better than multiple ones
  • Duplicate code prevention is between 25% - 30%
    • But this part is almost over 90% of the business rules
  • Fixing a bug for multiple platform/app is easier
  • Less config for CI/CD

References

  • https://monorepo.tools/

Thank you for listening

Monorepos in Action

By Özgün Bal

Monorepos in Action

  • 20