Skip to content

Project Structure

If you open the new project in VSCode you will see the following structure:

  • Directoryapi ## any thing related to api calls and data fetching
    • Directorycommon/
    • index.tsx
    • posts
    • types.ts
  • Directoryapp ## app routes and layouts
    • Directory(app)/
    • _layout.tsx
    • Directoryfeed/
    • login.tsx
    • onboarding.tsx
  • Directorycomponents ## any reusable components
    • Directoryui ## core ui and theme configuration
      • button.tsx
      • checkbox.tsx
      • colors.js
      • focus-aware-status-bar.tsx
      • icons
      • image.tsx
      • index.tsx
      • input.tsx
      • list.tsx
      • modal.tsx
      • progress-bar.tsx
      • select.tsx
      • text.tsx
      • utils.tsx
    • buttons.tsx
    • card.tsx
    • colors.tsx
    • cover.tsx
    • inputs.tsx
    • login-form.test.tsx
    • login-form.tsx
    • Directorysettings/
    • title.tsx
    • typography.tsx
  • Directorylib ## core files such as auth, localization, storage and more
    • auth
    • env.js
    • hooks
    • i18n
    • index.tsx
    • keyboard.ts
    • storage.tsx
    • test-utils.tsx
    • use-theme-config.tsx
    • utils.ts
  • Directorytranslations ## translation resources files
    • ar.json
    • en.json
  • Directorytypes ## global types
    • index.ts
  • components/ui: This folder contains all the UI components and the theme configuration. We provide minimal components with a basic obytes theme. You can add your own components and theme configuration here.

  • components: This folder contains the components of the app. mainly components used inside the app folder.

  • lib: This folder contains the core files, such as authentication, localization, storage, and more. It can be shared with other projects. That’s why we are only including modules that have nothing to do with project logic. This approach helps us share code between projects and also update the starter with new features.

  • app: This folder contains the routes of the app, along with its layout routes such as stack and tab navigation structures. We provide a basic navigation structure for the demo app that you can modify to fit your needs.

  • api: This folder contains the API files. We provide a basic API client and provider and you just need to create query and mutation for your modules. Check posts folder for inspiration on how to create a query and mutation.

  • translations: This folder contains the translation resources files. We recommend using translation files even if you are not supporting multiple languages as it will help you to support multiple languages in the future and also help you to find all the strings in one place.

  • types: This folder contains the global types.

Importing files

We use absolute imports to import files using the Babel module resolver plugin and TypeScript path mapping. This approach helps us avoid long relative paths and makes the code cleaner and more readable.

Here is a simple example of how the Feed screen looks with absolute imports.

src/app/(app)/index.tsx
import { FlashList } from '@shopify/flash-list';
import React from 'react';
import type { Post } from '@/api';
import { usePosts } from '@/api';
import { Card } from '@/components/card';
import { EmptyList, FocusAwareStatusBar, Text, View } from '@/components/ui';
export default function Feed() {
const { data, isPending, isError } = usePosts();
const renderItem = React.useCallback(
({ item }: { item: Post }) => <Card {...item} />,
[],
);
if (isError) {
return (
<View>
<Text> Error Loading data </Text>
</View>
);
}
return (
<View className="flex-1 ">
<FocusAwareStatusBar />
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={(_, index) => `item-${index}`}
ListEmptyComponent={<EmptyList isLoading={isPending} />}
estimatedItemSize={300}
/>
</View>
);
}

This approach is very useful when you are working on a large project with a lot of files and folders and it can be done by updating the babel.config.js file and tsconfig.json file to the following:

⚙️ Babel configuration
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [
['babel-preset-expo', { jsxImportSource: 'nativewind' }],
'nativewind/babel',
],
plugins: [
[
'module-resolver',
{
root: ['./'],
alias: {
'@': './src',
'@env': './src/lib/env.js',
},
extensions: [
'.ios.ts',
'.android.ts',
'.ts',
'.ios.tsx',
'.android.tsx',
'.tsx',
'.jsx',
'.js',
'.json',
],
},
],
'react-native-reanimated/plugin',
],
};
};
⚙️ Typescript Config
tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@env": ["./src/lib/env.js"]
},
"esModuleInterop": true,
"checkJs": true
},
"exclude": [
"node_modules",
"babel.config.js",
"metro.config.js",
"docs",
"cli",
"android",
"ios",
"lint-staged.config.js"
],
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
]
}